12장 immer를 사용하여 불변성 유지하기

mini·2022년 9월 1일
0

구조가 복잡한 객체도 매우 쉽고 짧은 코드를 사용하여 불변성을 유지하면서 업데이트 할수 있다.

  1. 프로 젝트 준비
$yarn create react-app immer-tutorial
$cd immer-tutorial
$yarn add immer
  1. immer 사용법
import produce from 'immer';
const nextState = produce(originalState, draft => {
	//바꾸고 싶은 값 바꾸기
    draft.somewhere.deep.indside = 5;
})

poduce라는 함수는 두가지 파라미터를 받는다. 1. 수정하고 싶은 상태, 2. 어떻게 업데이트 할지 정의하는 함수이다.
두번째 파라미터로 전달되는 함수 내부에서 원하는 값을 변경하면 produce 함수가 불변성을 유지를 대신 해주면서 새로운 상태를 생성해 준다. 불변성에 신경 쓰지않는것 처럼 코드를 작성 하되, 불변성 관리는 제대로 해주는 것. 배열을 처리할때도 유용

좀 더 복잡한 코드 예시

import produce from 'immer';

const originalState = [
	{
      id: 1,
      todo: '전개 연산자와 배열 내장 함수로 불변성 유지하기',
      checked: true,
    },
    {
      id: 2,
      todo: 'immer로 불변성 유지하기',
      checked: false,
    }
];


<실전 예시>
const nextState = produce(originalState, draft => {
	//id가 2인 항목의 checked 값을 true로 설정
    const todo = draft.find(t => t.id === 2); //id로 항목찾기
    todo.checked = true;
    // draft[1].checked = true;
    
    //배열에 새로운 데이터 추가
    draft.push({
    	id: 3,
        todo: '일정 관리 앱에 immer 적용하기',
        checked: false,
    })
    
    //id = 1 인 항목 제거
    draft.splice(draft.findIndex(t => t.id === 1), 1);
});

  //항목을 삭제하는 함수 
  const onRemove = useCallback(
    id => {
      setData(
        // {...data,
        // array: data.array.filter(info => info.id !== id)}
        produce(data, draft => {
          draft.array.splice(draft.array.findIndex(info => info.id === id), 1); //immer를 사용할때에는 splice, push 등 배열에 직접적으로 변화를 일으키는 함수를 써도 무방하다. 여기선 filter가 더 깔끔해 지므로 이렇게 써도 무방 불변성을 유지하는 코드가 복잡할때만 쓴다.
        })
      );
    },
    [data]
  );

useStatee의 함수형 업데이트와 immer 함께 쓰기

const [number, setNumber] = useState(0);
//prevNumber는 현재 number 값을 가리킨다.

const onIncrease = useCallback(
	() => setNumber(prevNumber => prevNumber + 1),
    [],
)

//immer 에서 제공하는 produce 함수를 호출할 때, 첫번째 파라미터가 함수 형태라면 업데이트 함수를 반환한다.

const update = produce(draft => {
	draft.value = 2;
})

const originalState = {
	value: 1,
    foo: 'bar',
}

const nextState = update(originalState);
console.log(nextState);

0개의 댓글