ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • React & Immer
    개발/React 2022. 6. 8. 13:34

    Immerjs 라는 라이브러리는 불변성 관리를 편하게 해줍니다.

    useState나 useReducer에서 상태 업데이트의 코드가 복잡하다면

    사용하는 것을 고려할 수 있습니다.

    다음 코드들의 출처는 공식 immer 페이지입니다.

     

    useState + Immer

    import React, { useCallback, useState } from "react";
    import produce from "immer";
    
    const TodoList = () => {
      const [todos, setTodos] = useState([
        {
          id: "React",
          title: "Learn React",
          done: true
        },
        {
          id: "Immer",
          title: "Try Immer",
          done: false
        }
      ]);
    
      const handleToggle = useCallback((id) => {
        setTodos(
          produce((draft) => {
            const todo = draft.find((todo) => todo.id === id);
            todo.done = !todo.done;
          })
        );
      }, []);
    
      const handleAdd = useCallback(() => {
        setTodos(
          produce((draft) => {
            draft.push({
              id: "todo_" + Math.random(),
              title: "A new todo",
              done: false
            });
          })
        );
      }, []);
    
      return (<div>{*/ See CodeSandbox */}</div>)
    }

     

    useImmer

    useImmer로도 상태 관리를 할 수 있습니다. 업데이트 함수 내부적으로 produce 안의 업데이트 로직을 감싸고 있습니다.

    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

     

    useReducer + Immer

    import React, {useCallback, useReducer} from "react"
    import produce from "immer"
    
    const TodoList = () => {
        const [todos, dispatch] = useReducer(
            produce((draft, action) => {
                switch (action.type) {
                    case "toggle":
                        const todo = draft.find(todo => todo.id === action.id)
                        todo.done = !todo.done
                        break
                    case "add":
                        draft.push({
                            id: action.id,
                            title: "A new todo",
                            done: false
                        })
                        break
                    default:
                        break
                }
            }),
            [
                /* initial todos */
            ]
        )
    
        const handleToggle = useCallback(id => {
            dispatch({
                type: "toggle",
                id
            })
        }, [])
    
        const handleAdd = useCallback(() => {
            dispatch({
                type: "add",
                id: "todo_" + Math.random()
            })
        }, [])
    
        // etc
    }

     

    Redux + Immer

    import produce from "immer"
    
    // Reducer with initial state
    const INITIAL_STATE = [
        /* bunch of todos */
    ]
    
    const todosReducer = produce((draft, action) => {
        switch (action.type) {
            case "toggle":
                const todo = draft.find(todo => todo.id === action.id)
                todo.done = !todo.done
                break
            case "add":
                draft.push({
                    id: action.id,
                    title: "A new todo",
                    done: false
                })
                break
            default:
                break
        }
    })

     

    댓글

Designed by Tistory.