개발자 도구로 성능체크

- 2500개의 데이터인 todos에 변화가 생기면 전체가 리렌더링 되어 성능저하
- '할 일 0' 체크하는데 한국인이라면 못 참을 렉이 걸림
- 렌더링 시간도 50m는 뛰어갈 수 있는 328.7ms나 걸림
- 그 이유는 '할 일 0'만 체크했는데 전체가 리렌더링 되기 때문. 의리 미쳤네
- 서로 영향을 주지 않기 위해 아래 코드로 수정
App.js
import React, { useCallback, useRef, useState } from 'react';
import TodoInsert from './components/TodoInsert';
import TodoList from './components/TodoList';
import TodoTemplate from './components/TodoTemplate';
function createBulkTodos() {
const array = [];
for(let i=0; i <= 2500; i++) {
array.push({
id: i,
text: `할 일 ${i}`,
checked: false,
});
}
return array;
}
function App() {
const [todos, setTodos] = useState(createBulkTodos);
const nextId = useRef(2501);
const onInsert = useCallback(text => {
const todo = {
id: nextId.current,
text,
checked: false,
};
setTodos(todos => todos.concat(todo));
nextId.current++;
}, []);
const onRemove = useCallback(id => {
setTodos(todos => todos.filter(todo => todo.id !== id))
}, []);
const onToggle = useCallback(id => {
setTodos(todos => todos.map(todo =>
todo.id === id ? {...todo, checked: true} : todo
))
}, []);
return (
<>
<TodoTemplate>
<TodoInsert onInsert={onInsert} />
<TodoList
todos={todos}
onRemove={onRemove}
onToggle={onToggle}
/>
</TodoTemplate>
</>
);
}
export default App;
TodoListItem.js
import React from 'react';
import {
MdCheckBoxOutlineBlank,
MdRemoveCircleOutline,
MdCheckBox
} from 'react-icons/md';
import cn from 'classnames';
import './TodoListItem.scss';
function TodoListItem({todo, onRemove, onToggle}) {
const {id, text, checked} = todo;
return (
<div className='TodoListItem'>
<div className={cn('checkbox', {checked})} onClick={() => onToggle(id)}>
{checked ? <MdCheckBox /> : <MdCheckBoxOutlineBlank />}
<div className='text'>{text}</div>
</div>
<div className="remove" onClick={() => onRemove(id)}>
<MdRemoveCircleOutline />
</div>
</div>
)
}
export default React.memo(TodoListItem);
React.memo()
- 컴포넌트 props가 바뀌지 않는다면 리렌더링 안 일어남
- React.memo(TodoListItem)처럼 원하는 컴포넌트 감싸주기
함수형 setState
- 하수들이 setState에 바로 원하는 값을 넣어줬다면 고수들은 함수형으로 넣어줌
- setState(prevValue => prevValue +1)처럼 매개변수로 업데이트 이전 값을 받아 상태변경 알려줌
- App.js에서 setTodos(todos => todos.filter(todo => todo.id !== id)), []);
- setTodos속 함수 매개변수 todos는 변수 todos가 아닌 업데이트 이전 값 todos
- 따라서 deps에 todos를 넣어줄 필요 없음
결과

- 렌더링 시간 줄어든 거 보소~~~
- 밑 그래프에 회식 빗금은 렌더링 되지 않은 아이들이다. 의리박살