[React] immer을 사용하여 더 쉽게 불변성 유지하기

soyeon·2022년 2월 15일
0
post-thumbnail

🎈 들어가며

<리액트를 다루는 기술> 12장 immer을 사용하여 더 쉽게 불변성 유지하기를 공부하면서 정리한 내용입니다📚
중간에 모르는 것들은 따로 서치를 해서 공부했습니다.

🎈 immer을 쓰는 이유

저번 포스트 [React] 컴포넌트 성능 최적화 에서 ...문법과 배열의 내장 함수로 배열을 얕은 복사해서 새로운 값을 덮어쓰는 방법을 썼는데요.

nextTodos[0] = {
  ...nextTodos[0], //기존 값들은 유지
  checked: false // 바꿔줄 값만 새로 할당
} // 새 객체를 할당

(대충 이런식)

만일에 여기서 더 나아가서 객체 안에 배열 안에 객체 안에 배열...같은 구조라면 어떨까요?

const object = {
	somwhere: {
    	deep: {
        	inside: 3,
          	array: [1,2,3,4]
        }
    }
};

이렇게 중첩된 배열이나 객체가 많은 경우 값 하나를 업데이트 하려면 하나하나 ...문법으로 기존 값을 가져와야합니다. 너무 귀찮죠.. 이를 보완하기 위해 나온 라이브러리가 immer입니다.

🎈 immer 설치 & 사용하기

immer 설치하기

npm install --save immer

import

import produce from 'immer';

immer 사용하기

🍧 produce(수정하고 싶은 state, state를 어떻게 업데이트할 지 정의하는 함수)

  • 두개의 인자를 다 넣으면 첫번째 인자에 넣은 state의 불변성을 유지하며 새로운 상태를 만들어줌
  • 첫번째 인자를 생략하고 바로 업데이트 함수를 넣어주면 새로운 state 대신 state를 업데이트 해주는 함수를 반환함.
  • 이를 이용해 setXXX 함수에 첫번째 함수를 생략하고 바로 업데이트 함수를 넣어줘서 코드를 간편하게 할 수 있다.

예제

immer을 쓰지 않고 불변성 유지(1)

  const [form, setForm] = useState({ name: '', username: '' });
  //input 수정을 위한 함수
  const onChange = useCallback(
    (e) => {
      const { name, value } = e.target;
      setForm({
        ...form,
        [name]: [value],
      });
    },
    [form]
  );

immer 사용(1)

  const onChange = useCallback(
    (e) => {
      const { name, value } = e.target;
      setForm(
        produce(draft => {
          draft[name] = value;
        })
      );
    },
    [form]
  );

immer을 쓰지 않고 불변성 유지(2)

      //array에 새 항목 등록
      setData({
        ...data,
        array: data.array.concat(info)
      })
  );

immer 사용(2)

      //array에 새 항목 등록
      setData(
        produce(draft=>{
          draft.array.push(info);
        })
      )
  • 객체 안에 있는 값을 직접 수정하거나 배열에 직접 변화를 일으키는 push, splice 등의 메서드를 사용해도 OK🤗
  • 새 항목을 추가할 때: concat, push
  • 항목을 제거할 때 : filter, splice

immer을 쓰지 않고 불변성 유지(3)

  const onRemove = useCallback(
    id => {
      setData({
        ...data,
        array: data.array.filter(info => info.id !== id)
      })
    }
    ,[data])

immer 사용(3)

      setData(
        produce(draft=>{
          draft.array.splice(draft.array.findIndex(info=>info.id===id),1)
          //해당하는 id의 객체의 index를 알아내고 그 부분만 도려냄
          //array.splice(startIndex, 삭제개수)
        })
      )

📎참고

<리액트를 다루는 기술> - 김민준(벨로퍼트), 길벗
23. Immer 를 사용한 더 쉬운 불변성 관리 - 벨로퍼트

profile
공부중

0개의 댓글