컴포넌트의 리렌더링을 방지할 때는 shoudComponentUpdate라는 라이프사이클을 사용하면 된다.
하지만, 함수형 컴포넌트에서는 shoudComponentUpdate같은 라이프사이클 메서드를 사용할 수 없다.
대신에 React.memo라는 함수를 사용하여,
컴포넌트의 props가 바뀌지 않았다면, 리렌더링 하지 않도록 설정하여 함수형 컴포넌트의 리렌더링 성능을 최적화해줄 수 있다.
const TodoList = ({ todos, onRemove, onToggle }) => {
return (
...
);
};
export default React.memo(TodoList); // 이렇게 React.memo로 감싸주기만 하면 된다.
const onRemove = useCallback((id) => {
setTodos(todos.filter((todo) => todo.id !== id));
}, [todos]);
위 코드는 useCallback을 이용해서 todos 배열을 감시하고 있다가 todos에 변경이 감지되면, setTodos() 함수를 매번 재생성한다.
이는 성능 악화의 주 원인이다.
setTodos()에서 함수형 업데이트를 이용하도록 하면 todos가 바뀔때마다 setTodos()함수를 매번 재생성할 필요가 없어진다.
함수형 업데이트를 이용하는 코드로 바꾸면 다음과 같다.
const onRemove = useCallback((id) => {
setTodos((todos) => todos.filter((todo) => todo.id !== id));
}, []);
react-virtualized 라이브러리를 이용하면, 컴포넌트 중에서 현재 화면에 보이지 않는 컴포넌트는 렌더링 하지 않고 크기만 차지하게끔 할 수 있다.
const TodoList = ({ todos, onRemove, onToggle }) => {
const rowRenderer = useCallback(
({ index, key, style }) => {
const todo = todos[index];
return (
<TodoListItem
todo={todo}
key={key}
onRemove={onRemove}
onToggle={onToggle}
style={style}
/>
);
},
[onRemove, onToggle, todos],
);
return (
<List
className="TodoList"
width={512}
height={513}
rowCount={todos.length}
rowHeight={57}
rowRenderer={rowRenderer}
list={todos}
style={{ outline: 'none' }}
/>
);
};
export default React.memo(TodoList);