All Articles

immer 라이브러리 사용하기

라이브러리 없이 순수하게 상태값 업데이트 하기

const fruits = ["오렌지", "사과", "레몬", "바나나"];

라는 배열에서 “사과”, “레몬”을 제거하고 그 자리에 “딸기”를 넣어보자.

나쁜 예

fruits.splice(1, 2, "딸기");
console.log(fruits);
> [ '오렌지', '딸기', '바나나' ]

원하는대로 변경하긴 했지만 fruits 객체(props)를 변경하므로 불변성 유지 실패

좋은 예

const newFruits = [
  ...fruits.slice(0, 1),
  "딸기",
  ...fruits.slice(3, 1)
];

새 배열 newFruits를 만들어서 원 배열은 유지한다.

fruits 배열을 풀어서(…) 0번 인덱스부터 1개 가져오고, 다음에 “딸기”를 넣고 다시 3번 인덱스부터 1개 가져온 뒤 배열([])로 묶어준다.

fruits와 newFruits를 보면 fruits는 원형 그대로, newFruits는 원하는대로 요소가 수정된 것을 확인할 수 있다.

console.log("fruits: ", fruits);
console.log("newFruits: ", newFruits);

> fruits: ['오렌지', '사과', '레몬', '바나나']
> newFruits: ['오렌지', '딸기', '바나나']

immer로 상태값 업데이트하기

우선 immer 라이브러리를 설치한다.

yarn add immer
import { produce } from "immer";

const newFruits = produce(fruits, draft => {
  draft.splice(1, 2, "딸기");
});

product 함수에는 base 객체, receipt 함수가 인자로 들어간다.

draft는 원본 fruits 복사본이다. 복사본을 splice 하는 것이므로 fruits 객체는 불변성을 유지한다.

console.log("fruits: ", fruits);
console.log("newFruits: ", newFruits);

> fruits: ['오렌지', '사과', '레몬', '바나나']
> newFruits: ['오렌지', '딸기', '바나나']

좀 더 연습해보기

const baseState = [
  {
    todo: "Learn typescript",
    done: true
  },
  {
    todo: "Try immer",
    done: false
  }
];
  • 두 번째 객체의 done을 true로 바꾸기
  • 배열 마지막 요소로 { todo: "Tweet about it" } 객체 추가하기

immer 사용하지 않기

const newState = [
  ...baseState.map(
    (tweet, index) => {
        return index !== 1 ? tweet : { ...tweet, done: true };
    }
  ),
  {
    todo: "Tweet about it",
  }
];

이건 컨닝했다 흑흑

baseState을 펼쳐서 map 함수로 각 객체와 그 인덱스 번호(키-값 쌍)를 저장한다.

1번 인덱스인 객체의 done 값을 true로 바꿔야 하므로, 인덱스가 1이 아닌 객체는 그대로 출력해주고 1일 때 done 키에 해당하는 값만 바꿔준다.

{ todo: “Tweet about it” } 는 새로 추가해야 하는 객체이므로 newState 배열 마지막 순서로 넣어준다.

비구조화와 삼항연산자를 잘 썼어야 하는 문제였다.

immer 사용하기

const newState = produce(baseState, draft => {
  draft[1].done = true;
  draft.push({ todo: "Tweet about it" });
})

두 케이스 모두 newState는 이렇게 나온다.

[
  { todo: 'Learn typescript', done: true },
  { todo: 'Try immer', done: true },
  { todo: 'Tweet about it' }
]