본문 바로가기

Redux

(Redux) Cannot add property 0, object is not extensible

체크박스 리스트를 만들고 신청 완료 후 체크박스를 초기화하는 기능을 추가하려고 한다.

 

기존에 useState 단위 컴포넌트에서 관리하여 상태를 

redux를 사용하여 전역으로 관리하고자 한다.

 

전역 상태 이름은 inquiryList이고 타입은 string[] 이다.

 

input 태그에 onChange 함수 handleChecked를 연결하여

체크가 될때마다 inquiryList를 업데이트해준다.

 

기존에 작성한 코드이다.

 

  const handleCheckItem = (value: string, isChecked: boolean) => {
    let copy = inquiryList

    if (isChecked) {
      copy.push(value)
    } else if (!isChecked && inquiryList.includes(value)) {
      copy = copy.filter(e => e !== value)
    }
    dispatch(updateInquiryList(copy))
  }

  const handleChecked = (e: React.ChangeEvent<HTMLInputElement>) => {
    setIsChecked(!isChecked)
    handleCheckItem(e.target.value, e.target.checked)
  }

 

체크하는 순간 마주한 에러 메세지.

 

변수 copy는 useSelector로 가져온 전역 저장소 변수 inquiryList를 담은 객체이다.

문제는 redux의 상태는 불변상태이다.

 

let copy = inquiryList 에서

copy에 담겨있는 것은 inquiryList안에 정보가 아닌

그 정보가 저장된 주소값이 저장되어 있다.

(얕은 복사라고 한다)

 

그리고 copy에 push(value) 하는 순간 

원본 inquiryList 데이터를 수정하려는 움직임이 있기 때문에

redux의 객체 불변성 원칙을 위배하면서 

'Cannot add property 0, object is not extensible' 라는 오류를 

마주하게 되는 것이다.(중요!!)

 

let copy = inquiryList와 같은 얕은 복사가 아닌

실제 값 자체를 복사해오는 깊은 복사를 하면 

위와 같은 불변성 유지의 원칙을 지킬 수 있다.

 

깊은 복사의 방법 중 흔히 사용되는 것은

spread operator이다. (전개 연산자)

 

let copy = [...inquiryList] 

... 와 같은 전개 문자로 깊은 복사를 할 수 있다.

깊은 복사도 중첩 객체의 경우에는 다른 방법을 사용해야 하는데

inquiryList는 one depth의 배열이기 때문에 전개 연산자로

해결이 가능하다.

 

 

'Redux' 카테고리의 다른 글

(Redux) 리덕스에서 사용되는 키워드  (0) 2021.12.31