StateManagement

i01029407043·2020년 8월 29일
0

3rdProject

목록 보기
1/1

React State의 불변성을 무시한 예시⭐️

Selected 배열을 다른 Component의 데이터와 취합해 BackEnd로 전달하기 위해 selected가 변경될 때마다 sessionStorage에 저장하는 function을 만들었다.

useEffect(() => {
    const selectedEl = selected.map((item) => {
      return item.name;
    });
    sessionStorage.setItem("selected", selectedEl);
  }, [selected]);

그런데 selected에 추가될 때는 잘 실행되던 function이 삭제할 때는 미동도 없는 현상이...?

Selected item의 onClick function

  <EachVariable
      onClick={() => {
         setArr([...arr, item]);
             selected.splice(selected.indexOf(item), 1);
                }}

selected.splice(selected.indexOf(item), 1); 여기에서 두 가지 문제를 발견했다.

  1. 먼저, splice method를 적용한 배열이 반환하는 값은 splice의 대상이 제외된 배열이 아니라, 대상이 되는 item이다.
    console.log(selected.splice(selected.indexOf(item), 1))
    즉 여기서 console.log를 확인해보면, 콘솔 창에서는 내가 클릭한 아이템을 확인할 수 있다. 이 아이템이 배열에서 splice되는 것이다.

  2. 위 코드에서는 selected 배열에 직접 접근했고, 새로운 배열로 setState해주지 않았다. React의 state를 업데이트 할 때, 기존의 데이터를 건드리지 않고 setState를 이용한다. 배열의 경우에도 마찬가지로 직접 push/pop하여 기존 배열을 변경하는 게 아니라 concat이나 spread operator를 사용한다. 여기서는 spread를 이용하기로 한다.

이 두 가지 문제를 해결한 코드는 다음과 같다.

  <EachVariable
      onClick={() => {
         setArr([...arr, item]);
            const selectedArr = [...selected];
            // 기존 배열을 변경하지 않는 새로운 배열을 변수에 담는다.
            selectedArr.splice(selected.indexOf(item), 1);
            // 새로운 배열에서 클릭한 item을 splice하고
            setSelected(selectedArr);   
            // selected를 새로운 배열로 setState한다.
               }}
              >

selected에 item 추가, 삭제 시 모두 sessionStorage에 업데이트 성공!

얼마 전 코어자바스크립트 독서모임에서 이야기했던 내용인데 실제 잘못 사용한 예시를 내 코드에서 보게 되다니 절망스럽기도 하고 반갑기도 했다 (?) 앞으로는 불변성 유지 꼭 유의하자!

관심 있을 만한 포스트

0개의 댓글