더북(TheBook)

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;

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