본문 바로가기
React

React - TypeScript 실행오류 Cannot add property, object is not extensible

by 새발개발JA 2022. 7. 27.
반응형

 

 

타입스크립트 에러가 났다.

readonly 객체는 수정할수 없기 때문에 에러가 난것이다. 

나의 경우는 redux 객체를 수정하려고 했기 때문에 에러가 나버렸다.

 

이 객체는 확장(수정)할수 없다.

 


React - TypeScript 실행오류  

Cannot add property, object is not extensible

 

리덕스 값(객체)는 직접 수정할 수 없다.  그 이유는 

  1. 상태 값은 불변 객체이다.
  2. 상태 값은 순수 함수에 의해서만 변경되어야 한다.

 

하지만 리덕스 객체를 직접 수정하려고 하니 당연히 나게된 에러였던 것이다.

객체를 직접 수정할 수 없다면 ? 복사해서 값을 고쳐주면 된다. (feat. 참조에 의한 복사)

 

** 참조에 의한 복사란 (더보기클릭)

더보기

객체를 만들면 객체 자체는 메모리에 저장되고, 변수에는 참조값만 저장이 된다. 

그렇기 때문에 실제로는 복사를 해도 객체의 참조 값이 복사되고 객체 자체는 복사되지 않는다.

우리는 참조값을 통해 객체를 수정하게 되는데 객체 안에 또 객체(a.k.a 중첩객체) 가 있는 경우에는

key 값까지 검사해주는 반복문을 사용해야 한다. (a.k.a 깊은 복사)

 

 

참조에 의한 객체 복사

 

ko.javascript.info

 

 

문제의 코드

리덕스 객체배열을 가져다가 값을 바꾸려고 하니 문제가 생겼다.

redux 값은 기본적으로 read only 이기 때문에 변경이 불가하다.

// msgs 는 리덕스 배열이다
// msgs 의 배열을 이루는 객체이고, 객체의 id 값을 변경하려는 상황이다.

function setMsgID(id: string, msgs: Message[]): void {
  for (let i = 0; i < msgs.length; i++) {
    const msg = msgs[i]; 
    
    if (msg.users) {
      for (let j = 0; j < msg.users.length; j++) {
        if (msg.users[j].id === id) {
          msg.msgID = msg.users[j].id; // >> 이부분에서 에러가 났다
          break;
        }
      }
    }
  }
}

 

 

해결의 코드 

원리는 간단하다. 원본 값을 변경 못한다면 복사해서 변경하면 된다.

객체를 복사해서 수정한 뒤, 복사 객체를 사용하면 된다.

export function setMsgID(id: string, msgs: Message[]): Message[] {
  return msgs.map(m => {	 // map() 자체는 새로운 배열을 리턴한다. 
    const msg = { ...m };    // item(객체) 단위로 복사한다.
    
    if (msg.users) {
      for (let j = 0; j < msg.users.length; j++) {
        if (msg.users[j].uid === uid) {
          msg.msgID = msg.users[j].id; // 복사된 item 의 값을 수정한다.
          break;
        }
      }
    }
    return msg; // 복사된 아이템을 통째로 리턴해버린다.
  });
}

 

 

자 이제 고친 값을 리덕스로 방생해주자

setMsgID(id, msgList);		 // 요함수를 거치면 수정된 객체 배열이 리턴되고
dispatch(setMsgList(msgList));   // 그걸 받아다가 dispatch 해서 redux 에 다시 저장시키면 된다.

 

 

 

 

 

 

 

반응형

댓글