Todo List성능 최적화 #04_useState 함수형 업데이트

React.memo 말고도 최적화 할 수 있는게 있다.
todos 배열이 업데이트 되면 onRemove, onToggle 함수가 배열 상태를 업데이트 하는 과정에서 최신 상태의 todos를 참조하기 때문에 todos 배열이 바뀔 떄마다 함수가 새로 만들어진다.

이렇게 함수가 매번 새로 만들어지는 것을 방지하기 위해 할 수 있는 방법은:

  • useState의 함수형 업데이트 기능을 사용

  • useReducer 사용




useState의 함수형 업데이트

기존에 setTodos 함수를 사용할 때는 새로운 상태를 parameter로 넣어주었다.
setTodos를 사용할 때 새로운 상태를 Parameter로 넣는 대신, 상태 업데이트를 어떻게 할지 정의해주는 업데이트 함수를 넣을 수도 있다. 이를 함수형 업데이트라고 한다.

예시:

const [number, setNumber] = useState(0);

// prevNumbers는 현재 number 값을 가리킵니다.
const onIncrease = useCallback(
  () => setNumber(prevNumber => prevNumber + 1),
  [],
);

setNumber(number+1)을 하는 것이 아니라, 위 코드처럼 어떻게 업데이트 할지 정의해주는 업데이트 함수를 넣어주면 된다. 그러면 useCallback을 사용할 때 두번째 Parameter로 넣는 배열에 number를 넣지 않아도 된다.





App.js에서 useState의 함수형 업데이트를 적용해보겠음.
(onInsert, onRemove, onToggle에 적용 ㄱㄱ)

App.js

import React, { useState, useRef, useCallback } from 'react';
import TodoInsert from './components/TodoInsert';
import TodoList from './components/TodoList';
import TodoTemplate from './components/TodoTemplate';


function createBulkTodos() {
  const array = [];
  for (let i = 1; i <= 2500; i++) {
    array.push({
      id: 1,
      text: `할 일 ${i}`,
      checked: false,
    });
  }
  return array;
}


const App = () => {
  const [todos, setTodos] = useState(createBulkTodos);



// 고윳값으로 사용될 id
  // ref를 사용하여 변수 담기
  const nextId = useRef(4);



const onInsert = useCallback(text => {
    const todo = {
      id: nextId.current,
      text,
      checked: false,
    };
    setTodos(todos => todos.concat(todo));		//"todos =>" 추가함.
    nextId.current += 1; // nextId 1씩 더하기
  }, []);



const onRemove = useCallback(id => {
    setTodos(todos => todos.filter(todo => todo.id != = id)); //"todos =>" 추가함.
  }, []);



const onToggle = useCallback(id => {
    setTodos(todos =>			//"todos =>" 추가함.
      todos.map(todo =>
        todo.id === id ? { …todo, checked: !todo.checked } : todo,
      ),
    );
  }, []);



return (
    <TodoTemplate>
      <TodoInsert onInsert={onInsert} />
      <TodoList todos={todos} onRemove={onRemove} onToggle={onToggle} />
    </TodoTemplate>
  );
};



export default App;

기존에 onInsert의경우
setTodos(todos.concat(todo));에서
setTodos(todos => todos.concat(todo)); 이렇게 수정함.
setTodos의 ()안에 맨 앞쪽에 "todos =>" 이거만 추가해줬음.

좋은 웹페이지 즐겨찾기