(생략)
function createBulkTodo() {
const array = [];
for (let i = 0; i <= 2500; i++) {
array.push({
id: i,
text: `할 일 ${i}`,
checked: false,
});
}
}
const App = () => {
const [todos, setTodos] = useState(createBulkTodo);
(생략)
};
export default App;
useState(createBulkTodo())
의 경우
→ 리렌더링될 때마다 createBulkTodo
함수 호출
useState(createBulkTodo)
의 경우
== 파라미터: 함수 형태
→ 컴포넌트가 처음 렌더링될 때만 createBulkTodo
함수 실행
shouldComponentUpdate
(라이프사이클) 사용React.memo
사용컴포넌트 props 변화x → 리렌더링x
사용법
컴포넌트 감싸기
(생략)
export default React.memo(컴포넌트명);
setState의 파라미터에 업데이트 함수를 넣는 것
업데이트 함수란?
상태 업데이트를 어떻게 할지 정의
const [number, setNumber] = useState(0);
const onIncrease = useCallback(
() => setNumber( number + 1 ),
[number],
)
const [number, setNumber] = useState(0);
// prevNumbers === 현재 number 값
const onIncrease = useCallback(
() => setNumber(prevNumber => prevNumbers + 1),
[],
)
참고
prevNumber =>
추가한 것과 배열([]
) 만 변화
import React, { useRef, useCallback, useReducer } from 'react';
import TodoTemplate from './components/TodoTemplate';
import TodoInsert from './components/TodoInsert';
import TodoList from './components/TodoList';
function createBulkTodos() {
const array = [];
for (let i = 0; i <= 2500; i++) {
array.push({
id: i,
text: `할 일 ${i}`,
checked: false,
});
}
return array;
}
function todoReducer(todos, action) {
switch (action.type) {
case 'INSERT': // 추가
// { type: 'INSERT', todo: { id: 2501, text: '할일 2501', checked: false } }
return todos.concat(action.todo);
case 'REMOVE': // 삭제
// { type: 'REMOVE', id: 1 }
return todos.filter((todo) => todo.id !== action.id);
case 'TOGGLE': // 토글
// { type: 'TOGGLE', id: 1 }
return todos.map((todo) =>
todo.id === action.id ? { ...todo, checked: !todo.checked } : todo,
);
default:
return todos;
}
}
const App = () => {
const [todos, dispatch] = useReducer(todoReducer, undefined, createBulkTodos);
// 고유 값으로 사용 될 id
// ref 를 사용하여 변수 담기
const nextId = useRef(2501);
const onInsert = useCallback((text) => {
const todo = {
id: nextId.current,
text,
checked: false,
};
dispatch({ type: 'INSERT', todo });
nextId.current += 1; // nextId 1 씩 더하기
}, []);
const onRemove = useCallback((id) => {
dispatch({ type: 'REMOVE', id });
}, []);
const onToggle = useCallback((id) => {
dispatch({ type: 'TOGGLE', id });
}, []);
return (
<TodoTemplate>
<TodoInsert onInsert={onInsert} />
<TodoList todos={todos} onRemove={onRemove} onToggle={onToggle} />
</TodoTemplate>
);
};
export default App;
useReducer
두 번째 파라미터 = 초기 상태undefined
createBulkTodos
)(컴포넌트가) 맨 처음 렌더링될 때만 함수(createBulkTodos
) 호출
단점
기존 코드 많이 고쳐야 함
장점
상태 업데이트 로직들 → 컴포넌트 바깥에 둘 수 있음.
→ 취향에 따라 선택
관련 컴포넌트 → 같이 최적화
예시
'리스트' 관련 컴포넌트 최적화할 때
→ (리스트 내부 + 리스트 자체) 컴포넌트 모두 최적화 해야 함.
이유
미리 최적화 시키는 것 (추후 발생 가능한 불필요한 렌더링 대비)
당장 불필요한 렌더링이 발생 x 해도
추후 관련된 타 컴포넌트에서 변화가 생겨 불필요한 렌더링 생길 가능성 有
→ 미리 대비/성능 최적화(React.memo활용)