Immer

webDev5·2024년 11월 29일

패키지

목록 보기
3/3

Immer

  • 독일어로 항상이라는 뜻
  • 불변성을 유지하면서 편하게 작업할 수 있는 패키지

간단한 사용 예시

const baseState = [
  {
    title: "Learn TypeScript",
    done: true,
  },
  {
    title: "Try Immer",
    done: false,
  },
];
  • 위와 같은 코드를 작업해야할 경우
const nextState = baseState.slice();
nextState[1] = {
  ...nextState[1],
  done: true,
};

nextState.push({ title: "Tweet about it" });
  • Immer 패키지가 없다면 위와 같이 작업해야 함
import { produce } from "immer";

const nextState = produce(baseState, (draft) => {
  draft[1].done = true;
  draft.push({ title: "Tweet about it" });
});
  • Immer 패키지가 있으면 위와 같이 간단하게 처리할 수 있음

설치

  • Yarn: yarn add immer
  • NPM: npm install immer

주의점

  • Immer는 자바스크립트 엔진의 프록시 기능을 사용
  • 프록시 기능을 지원하지 않는 경우, ES5의 문법을 사용하는데 속도가 느려짐

produce

import { produce } from "immer";

const baseState = [
  {
    title: "Learn TypeScript",
    done: true,
  },
  {
    title: "Try Immer",
    done: false,
  },
];

const nextState = produce(baseState, (draftState) => {
  draftState.push({ title: "Tweet about it" });
  draftState[1].done = true;
});
  • produce(baseState, recipe: (draftState) => void): nextState
    • baseState: 작업할 객체
    • recipe: 객체를 작업하는 콜백 함수
    • draftState: recipe의 기본 상태의 프록시

응용

import { produce } from "immer";

function toggleTodo(state, id) {
  return produce(state, (draft) => {
    const todo = draft.find((todo) => todo.id === id);
    todo.done = !todo.done;
  });
}

const baseState = [
  {
    id: "JavaScript",
    title: "Learn TypeScript",
    done: true,
  },
  {
    id: "Immer",
    title: "Try Immer",
    done: false,
  },
];

const nextState = toggleTodo(baseState, "Immer");
  • 위와 같이 produce 함수 자체를 반환해서 간단하게 사용 가능

useImmer

import React, { useCallback } from "react";
import { useImmer } from "use-immer";

const TodoList = () => {
  const [todos, setTodos] = useImmer([
    {
      id: "React",
      title: "Learn React",
      done: true
    },
    {
      id: "Immer",
      title: "Try Immer",
      done: false
    }
  ]);

  const handleToggle = useCallback((id) => {
    setTodos((draft) => {
      const todo = draft.find((todo) => todo.id === id);
      todo.done = !todo.done;
    });
  }, []);

  const handleAdd = useCallback(() => {
    setTodos((draft) => {
      draft.push({
        id: "todo_" + Math.random(),
        title: "A new todo",
        done: false
      });
    });
  }, []);
  // etc
  • useState + Immer
  • 리액트에서 사용할 수 있는 Hook
  • useState와 사용 방법은 동일

출처

profile
공부한 내용을 정리하는 블로그입니다.

0개의 댓글