리액트를 다루는 기술 개정판 [IMMER 불변성 유지]
12. immer를 사용하여 더 쉽게 불변성 유지하기
- 전개 연산자와 배열의 내장 함수를 사용하면 간단하게 객체를 복사 및 갱신이 가능하다.
- 하지만, 객체의 구조가 엄청나게 깊어지면 불변성을 유지하면서 이를 업데이트하는 것이 힘들어진다.
- immer를 사용하면 구조가 복잡한 객체도 매우 쉽고 짧은 코드를 사용하며 불변성을 유지하며 업데이트할 수 있다.
- immer 설치
$ yarn create react-app immer-tutorial
$ cd immer-tutorial
$ yarn add immer
- immer 사용법
Ex 1)
import produce from 'immer';
const nextState = produce(originalState, draft => {
// 바꾸고 싶은 값 바꾸기
draft.somewhere.deep.inside = 5;
})
. produce라는 함수는 두개의 파라미터를 받는다; (1) 수정하고 싶은 상태, (2) 상태를 어떻게 업데이트할지
. 함수 내부에서 원하는 값을 변경하면, produce 함수가 불변성 유지를 대신해 주면서 새로운 상태를 생성한다.
. *핵심: 불변성에 신경 쓰지 않는 것처럼 코드를 작성하되 불변성 관리는 제대로 해 주는 것
. 배열을 처리할 때도 매우 쉽고 편하다.
Ex 2)
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);
todo.checked = true;
// 배열에 새로운 데이터 추가
draft.push({
id: 3,
todo: '일정 관리 앱에 immer 적용하기',
checked: false,
});
// id = 1인 항목을 제거하기
draft.splice(draft.findIndex(t => t.id === 1), 1);
});
const nextState = produce(originalState, draft => {
// 바꾸고 싶은 값 바꾸기
draft.somewhere.deep.inside = 5;
})
. immer를 사용하면 객체 내부 값을 직접 수정하거나, 배열에 직접적인 변화를 일으키는 push, splice 등의 함수를 사용해도 무방하다.
. 그러나, immer를 사용하면 무조건 코드가 간결해지는 것은 아니다. (onRemove의 경우, filter를 사용하는 것이 더 깔끔하다.)
-> immer는 코드가 복잡해질 때만 사용하자.
. immer와 useState를 함께 사용하기
. immer에서 제공하는 produce 함수를 호출할 때, 첫 번째 파라미터가 함수 형태라면 업데이트 함수를 반환한다. (변수 불필요)
const update = produce(draft => {
draft.value = 2;
});
const originalState = {
value: 1,
foo: 'bar',
};
const nextState = update(originalState);
console.log(nextState); // {value: 2, foo: 'bar'}
. immer는 리덕스와 함께 쓰면 매우 쉽게 코드를 작성할 수 있다.
. 절대 필수는 아니다.