티스토리 뷰

다음은 todo list의 일부 코드이다.

각각의 할 일을 완료 여부를 클릭할 때마다 다른 할 일 목록도 리렌더링 되는 문제가 발생한다.

 

리렌더링을 방지하기 위해서 2가지 방법이 있다.

 

memo 사용 방법

import { memo } from "react";

const TodoItem = ({ todo, onDelete, updateDone }) => {
  const onClickButton = () => {
    onDelete(todo.id);
  };

  const onChangeIsDone = () => {
    updateDone(todo.id);
  };

  return (
    <div className="TodoItem">
      <input type="checkbox" value={todo.isDone} onChange={onChangeIsDone} />
      <div className="content">{todo.content}</div>
      <div className="date">{new Date(todo.date).toLocaleDateString()}</div>
      <button onClick={onClickButton}>삭제</button>
    </div>
  );
};

// memo 메서드는 얕은 비교를 하기때문에 리렌더링될때 
// onDelete, updateDone 함수가 매번 생성되어 변경되었다고 판단
export default memo(TodoItem, (preProps, nextProps) => {
  // true -> props 바꾸지 않음, false -> props 바뀜
  if (preProps.todo !== nextProps.todo) return false;
  return true;
});

 

memo 두번째 인자로 콜백 함수(callback)를 추가할 수 있다. 

콜백 함수에는 인자로 이전 props, 변경 후 props 값을 받는다.

이 값을 비교해서 todo의 값이 변경 됐을때만 렌더링 하도록 지시할 수 있다.

문제는 props 갯수가 변경되면 조건을 추가해야 하고, 이름이 변경되면 콜백 함수 코드도 손을 댈 수밖에 없는 단점이 있다.

유지보수에 좋지 않다.

 

useCallback 사용 방법

아래와 같이 컴포넌트가 리랜더링 되더라도 함수가 생성되지 않도록 아래처럼 코드를 구현하면 된다.

useCallback에 의존성 배열을 빈 배열로 할당하면 mounted 될때만 해당 함수가 생성되고 그 이후에 리렌더링 되더라도 생성되지 않게 막을 수 있다.

  // TodoItem parent 
  const onDelete = useCallback((targetId) => {
    dispatch({
      type: "DELETE",
      targetId: targetId,
    });
  }, []);

  const updateDone = useCallback((targetId) => {
    dispatch({
      type: "UPDATE",
      targetId: targetId,
    });
  }, []);
  
  
  // TodoItem component
  export default memo(TodoItem);

 

 

 

memo에 콜백 함수를 사용하는것 보다 더 깔끔하고 유지보수에도 편한 이 방법이 더 낫다.

728x90
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2026/01   »
1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30 31
글 보관함