11.5.2 useReducer 사용하기

    useState의 함수형 업데이트를 사용하는 대신, useReducer를 사용해도 onToggleonRemove가 계속 새로워지는 문제를 해결할 수 있습니다.

    코드를 다음과 같이 한번 고쳐보세요.

    App.js

    import React, { useReducer, useRef, useCallback } from 'react';
    import TodoTemplate from './components/TodoTemplate';
    import TodoInsert from './components/TodoInsert';
    import TodoList from './components/TodoList';
     
    function createBulkTodos() {
      const array = [];
      for (let i = 1; i <= 2500; i++) {
        array.push({
          id: i,
          text: `  ${i}`,
          checked: false,
        });
      }
      return array;
    }
     
    function todoReducer(todos, action) {
      switch (action.type) {
        case 'INSERT': // 새로 추가
          // { type: 'INSERT', todo: { id: 1, text: 'todo', checked: false } }
          return todos.concat(action.todo);
        case 'REMOVE': // 제거
          // { type: 'REMOVE', id: 1 }
          return todos.filter(todo => todo.id != = action.id);
        case 'TOGGLE': // 토글
          // { type: 'REMOVE', id: 1 }
          return todos.map(todo =>
            todo.id === action.id ? { ...todo, checked: !todo.checked } : todo,
          );
        default:
          return todos;
      }
    }
     
    const App = () => {
      const [todos, dispatch] = useReducer(todoReducer, undefined, createBulkTodos);
     
      // 고윳값으로 사용될 id
      // ref 사용하여 변수 담기
      const nextId = useRef(2501);
     
      const onInsert = useCallback(text => {
        const todo = {
          id: nextId.current,
          text,
          checked: false,
        };
        dispatch({ type: 'INSERT', todo });
        nextId.current += 1; // nextId 1 더하기
      }, []);
     
      const onRemove = useCallback(id => {
        dispatch({ type: 'REMOVE', id });
      }, []);
     
      const onToggle = useCallback(id => {
        dispatch({ type: 'TOGGLE', id });
      }, []);
     
      return (
        <TodoTemplate>
          <TodoInsert onInsert={onInsert} />
          <TodoList todos={todos} onRemove={onRemove} onToggle={onToggle} />
        </TodoTemplate>
      );
    };
     
    export default App;

    신간 소식 구독하기
    뉴스레터에 가입하시고 이메일로 신간 소식을 받아 보세요.