반응형
타입스크립트 에러가 났다.
readonly 객체는 수정할수 없기 때문에 에러가 난것이다.
나의 경우는 redux 객체를 수정하려고 했기 때문에 에러가 나버렸다.
React - TypeScript 실행오류
Cannot add property, object is not extensible
리덕스 값(객체)는 직접 수정할 수 없다. 그 이유는
- 상태 값은 불변 객체이다.
- 상태 값은 순수 함수에 의해서만 변경되어야 한다.
하지만 리덕스 객체를 직접 수정하려고 하니 당연히 나게된 에러였던 것이다.
객체를 직접 수정할 수 없다면 ? 복사해서 값을 고쳐주면 된다. (feat. 참조에 의한 복사)
** 참조에 의한 복사란 (더보기클릭)
더보기
객체를 만들면 객체 자체는 메모리에 저장되고, 변수에는 참조값만 저장이 된다.
그렇기 때문에 실제로는 복사를 해도 객체의 참조 값이 복사되고 객체 자체는 복사되지 않는다.
우리는 참조값을 통해 객체를 수정하게 되는데 객체 안에 또 객체(a.k.a 중첩객체) 가 있는 경우에는
key 값까지 검사해주는 반복문을 사용해야 한다. (a.k.a 깊은 복사)
문제의 코드
리덕스 객체배열을 가져다가 값을 바꾸려고 하니 문제가 생겼다.
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 에 다시 저장시키면 된다.
반응형
'React' 카테고리의 다른 글
React(80) 객체 값을 동적으로 할당하기 (0) | 2022.08.18 |
---|---|
React(79) 숫자 세자리 마다 콤마 붙이기(comma seperator) (0) | 2022.08.13 |
React(78) useEffect 에서 스크롤 이벤트 동작원리(feat. addEventListener) (0) | 2022.07.18 |
React(77) 스크롤 시, 하위메뉴를 헤더 아래로 고정하기 (0) | 2022.07.12 |
React(76) TypeScript - 채팅목록에서 마지막 메시지 보여주기 (1) | 2022.06.27 |
댓글