해당 책은 리액트를 다루는 기술 11장을 기반으로 작성된 글입니다.

데이터가 무수히 많아지면 애플리케이션이 느려지는 것을 체감할 수 있을 정도로 지연이 발생한다.
실제 랙이 걸릴 정도의 많은 데이터를 렌더링해 보자.
App.js 컴포넌트를 다음과 같이 수정해 보자.
import React, { useState, 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: </span><span class="cd2 co31">할</span> <span class="cd2 co31">일</span> <span class="cd2 co49">${</span><span class="cd2 co33">i</span><span class="cd2 co49">}</span><span class="cd2 co31">,
checked: false,
});
}
return array;
}
const App = () => {
const [todos, setTodos] = useState(createBulkTodos);
// 고윳값으로 사용될 id
// ref를 사용하여 변수 담기
const nextId = useRef(2501);
(…)
};
export default App;

할 일이 2500개가 된다.
useState에 useState(createBulkTodos())라고 작성하면 리렌더링 될 때마다 함수가 호출되지만, useState(createBulkTodos)처럼 함수 형태로 넣어 주면 컴포넌트가 처음 렌더링될때만 createBulkTodos함수가 실행된다.
크롬 개발자 도구의 Performance탭을 사용하면 몇 초가 걸리는지 확인할 수 있다.

컴포넌트는 다음과 같은 상황에서 리렌더링이 발생한다.
1. 자신이 전달받은 props가 변경될 때
2. 자신의 state가 바뀔 때
3. 부모 컴포넌트가 리렌더링 될 때
4. forceUpdate함수가 실행될 때
지금 상황을 분석하면, 할 일1항목을 체크할 경우, App 컴포넌트의 state가 변경되면서 App컴포넌트가 리렌더링 된다. 부모 컴포넌트가 리렌더링 되었으니 TodoList 컴포넌트가 리렌더링 되고, 그 안의 무수한 컴포넌트들도 리렌더링 된다.
할 일1 항목만 리렌더링 되어야 하는데, 할 일2~할 일2500까지 리렌더링 되고 있으니 느린 것이다.
이 때 컴포넌트 리렌더링 성능 최적화 작업이 필요하다.
컴포넌트의 래렌더링 방지를 위해 7장에서 배운 shouldComponentUpdate라는 라이프사이클을 사용하면 된다.
다만 함수형 컴포넌트에는 라이프사이클 메서드를 사용할 수 없으므로, React.memo 함수를 사용한다. 컴포넌트의 props가 바뀌지 않았다면, 리렌더링 하지 않도록 설정하여 함수형 컴포넌트 리렌더링 성능을 최적화해줄 수 있다.
컴포넌트를 만들고 나서 감싸주기만 하면 React.memo를 사용할 수 있다.
import React from ‘react‘;
import {
MdCheckBoxOutlineBlank,
MdCheckBox,
MdRemoveCircleOutline,
} from ‘react-icons/md‘;
import cn from ‘classnames‘;
import ‘./TodoListItem.scss‘;
const TodoListItem = ({ todo, onRemove, onToggle }) => {
(…)
};
export default React.memo(TodoListItem);