[React] TypeError: Cannot assign to read only property '0' of object '[object Array]'

박기영·2022년 10월 6일
3

React

목록 보기
16/32
post-thumbnail

제목에 있는 오류에 대한 해결법을 작성하고자 한다.
변경할 수 없는 배열에 대한 변경을 시도했을 경우 발생하는 에러이다.
필자는 TS + Redux Toolkit으로 받아온 데이터를 수정하고자 했고,
useSelector를 활용하여 스토어에서 꺼내온 데이터를 직접 수정하고자 했을 때
이 에러가 발생했다.

문제 상황

필자는 api 통신 결과로 받아온 데이터를 리덕스 스토어에 넣은 뒤,
useSelector로 스토어에서 값을 꺼내왔고,
그 데이터 중, 배열 타입의 데이터를 reverse() 해서 보여주고 싶었다.

데이터가 잘 처리되었는지 console.log()로 확인하고자 아래 코드로 진행했다.

// 스토어에서 데이터 가져오기
const lectureData = useAppSelector((state) => state.lecture.lectureData);

// api 통신으로 받아온 데이터를 스토어에 저장하고
// 그 중, 원하는 특정 데이터(배열)을 가지고 setState 해줌.
useEffect(() => {
  dispatch(loadAllLecture(null))
    .then((res) => {
	  if (res.payload?.lectureList) {
		setLectureList(res.payload.lectureList);
      }
    })
    .catch((err) => console.log(err));
}, []);

// setState의 비동기 처리로 인한 에러를 막기 위해
// useEffect를 사용하여 데이터를 처리해줬다.
useEffect(() => {
  let arr = lectureData.lectureList.reverse();
  console.log(arr);
}, [lectureList]);

가장 아래 부분에 있는 reverse()가 문제의 코드이다.
저 부분을 작성하기 전까지는 아무런 문제가 없다가, 저 코드가 추가된 직후에

참고 이미지

이런 에러가 발생했다.

주목할 점은 read only이다.
읽기 전용 데이터를 필자가 바꾸려고 했기 때문에 에러가 발생한 것이다.

해결 방법은 깊은 복사이다.
쉽게 말해, 변경할 수 없던 데이터를 복사해서 다른 변수에 넣고, 그 값을 수정하는 것이다.

깊은 복사

// 스토어에서 데이터 가져오기
const lectureData = useAppSelector((state) => state.lecture.lectureData);

// api 통신으로 받아온 데이터를 스토어에 저장하고
// 그 중, 원하는 특정 데이터(배열)을 가지고 setState 해줌.
useEffect(() => {
  dispatch(loadAllLecture(null))
    .then((res) => {
	  if (res.payload?.lectureList) {
		setLectureList(res.payload.lectureList);
      }
    })
    .catch((err) => console.log(err));
}, []);

// setState의 비동기 처리로 인한 에러를 막기 위해
// useEffect를 사용하여 데이터를 처리해줬다.
useEffect(() => {
  // 위에서 실행된 useEffect에서 lectureList라는 state를 set했었다.
  // 그 state를 그대로 복사해줬다.(깊은 복사)
  let arr = [...lectureList];

  // 이제 데이터를 수정해도 전혀 에러가 없다!
  arr.reverse();

  setReversedLectureList(arr);
}, [lectureList]);

아까 봤던 코드와 지금 코드의 차이가 뭘까?
스프레드 연산자(Spread Operator) ...을 사용했다는 것이다.

사실 스프레드 연산자가 깊은 복사인지 얕은 복사인지에 대한 말이 사람마다 꽤 다른 것 같은데..
적어도 필자가 알아본 자료들에 의하면 깊은 복사가 맞다는 말이 더 많다.

medium에서 많은 추천을 받은 분의 말을 인용하자면

The spread operator makes deep copies of data if the data is not nested.
- Kevin Lai -

직역하자면 "중첩된 데이터가 아니라면 스프레드 연산자는 깊은 복사가 된다."이다.

이 것에 관련해서는 참고 자료에 링크를 남겨두도록 하겠다.
깊은 복사와 얕은 복사에 대해서도 정확하게 정리해야겠다.

참고 자료

tchaikovsky님 블로그
akjfal님 블로그
Kevin Lai님 블로그

profile
나를 믿는 사람들을, 실망시키지 않도록

0개의 댓글