ํจ์ ์ปดํฌ๋ํธ์์ React.memo() ํจ์๋ฅผ ์ฌ์ฉํ๋ ๊ฒ๋ง์ผ๋ก ์ปดํฌ๋ํธ ์ต์ ํ๊ฐ ๋๋์ง๋ ์๋๋ค.
์๋ฅผ ๋ค์ด ์ต์ ์ํ์ todos ๋ฅผ ์ฐธ์กฐํ๋ onClick ๊ฐ์ ํจ์๊ฐ ์์ด์ todos ๋ฐฐ์ด์ด ๋ฐ๋ ๋๋ง๋ค ํจ์๊ฐ ์๋ก ๋ง๋ค์ด์ง๋ค๊ณ ํ ๋, ์ด๋ ๊ฒ ํจ์๊ฐ ๊ณ์ ๋ง๋ค์ด์ง๋ ์ํฉ์ ๋ฐฉ์งํ๋ ๋ฐฉ๋ฒ์ ๋ ๊ฐ์ง์ด๋ค.
1. useState ์ ํจ์ํ ์ ๋ฐ์ดํธ ๊ธฐ๋ฅ ์ฌ์ฉํ๊ธฐ
์๋ฅผ ๋ค์ด ๊ธฐ์กด์ setTodos ํจ์๋ฅผ ์ฌ์ฉํ๋ค๊ณ ํ๋ฉด, ์ด ํจ์๋ฅผ ์ฌ์ฉํ ๋ ์๋ก์ด ์ํ๋ฅผ ํ๋ผ๋ฏธํฐ๋ก ๋ฃ๋ ๋์ ์ํ ์ ๋ฐ์ดํธ๋ฅผ ์ด๋ป๊ฒ ํ ์ง ์ ์ํด์ฃผ๋ ์ ๋ฐ์ดํธ ํจ์๋ฅผ ๋ฃ์์ผ๋ก์จ ํจ์ํ ์ ๋ฐ์ดํธ๋ฅผ ํ ์ ์๋ค.
setNumber(number+1) ์ด ์๋๋ผ setNumber(preNumber => preNumber + 1) ๊ณผ ๊ฐ์ ์ ๋ฐ์ดํธ ํจ์๋ฅผ ๋ฃ์ด์ค๋ค.
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: !todo.checked} : todo,
),
);
}, []);
// const onToggle = useCallback(id => {
// setTodos(todos.map(todo => todo.id === id ? {...todo, checked: !todo.checked} : todo,
// ),
// );
// }, [todos],);
2. useReducer ์ฌ์ฉํ๊ธฐ
import TodoInsert from "./components/TodoInsert";
import TodoTemplate from "./components/TodoTemplate";
import TodoList from "./components/TodoList";
import { useReducer, useState, useRef, useCallback } from "react";
function createBulkTodos() {
const array = [];
for (let i = 1; i <= 2500; i++) {
array.push({
id: 1,
text: `ํ ์ผ ${i}`,
checked: false,
});
}
return array;
}
// useReducer ์ถ๊ฐ๋ ์ฝ๋
function todoReducer(todos, action) {
switch (action.type) {
case "INSERT":
return todos.concat(action.todo);
case "REMOVE":
return todos.filter((todo) => todo.id !== action.id);
case "TOGGLE":
return todos.map((todo) =>
todo.id === action.id ? { ...todo, checked: !todo.checked } : todo
);
default:
return todos;
}
}
// ---------------------------- ์ด๊น์ง
const App = () => {
// createBulkTodos() ํํ๋ก ํ๋ผ๋ฏธํฐ๋ฅผ ๋ฃ์ด ์ฃผ๋ฉด ์ปดํฌ๋ํธ๊ฐ ๋ฆฌ๋ ๋๋ง ๋ ๋๋ง๋ค ํจ์๊ฐ ์คํ๋๋ค.
// createBulkTodos ์ฒ๋ผ ํจ์ ํํ๋ก ๋ฃ์ด ์ฃผ๋ฉด ์ปดํฌ๋ํธ๊ฐ ์ฒ์ ๋ ๋๋ง ๋ ๋๋ง ํจ์๊ฐ ์คํ๋๋ค.
const [todos, dispatch] = useReducer(todoReducer, undefined, createBulkTodos);
const nextId = useRef(2501);
// ํ ์ผ ์ถ๊ฐ
const onInsert = useCallback((text) => {
const todo = {
id: nextId.current,
text,
checked: false,
};
dispatch({ type: "INSERT", todo });
nextId.current += 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 ํจ์๊ฐ ํธ์ถ๋๋ค.
โ ๋ฆฌ์คํธ ๊ด๋ จ ์ปดํฌ๋ํธ๋ฅผ ์์ฑํ ๋ ๋ฐ์ดํฐ๊ฐ 100 ๊ฐ ์ด์์ด๊ฑฐ๋ ์ ๋ฐ์ดํธ๊ฐ ์์ฃผ ๋ฐ์ํ๋ค๋ฉด, ๋ฆฌ์คํธ ์์ดํ ๊ณผ ๋ฆฌ์คํธ, ์ด ๋ ๊ฐ์ง ์ปดํฌ๋ํธ ๋ฐ๋์ ์ต์ ํํด์ฃผ๊ธฐ
3. react-virtualized ์ฌ์ฉํ๊ธฐ
๋ฆฌ์คํธ ์ปดํฌ๋ํธ์์ ์คํฌ๋กค ๋๊ธฐ ์ ์ ๋ณด์ด์ง ์๋ ์ปดํฌ๋ํธ๋ ๋ ๋๋งํ์ง ์๊ณ ํฌ๊ธฐ๋ง ์ฐจ์งํ๊ฒ๋ ํ ์ ์๋ค. ๋ฐ๋ผ์ ์คํฌ๋กค ๋๋ฉด ํด๋น ์คํฌ๋กค ์์น์์ ๋ณด์ฌ์ฃผ์ด์ผ ํ ์ปดํฌ๋ํธ๋ฅผ ์์ฐ์ค๋ฝ๊ฒ ๋ ๋๋งํ๋ ๊ฒ์ด๋ค.
# ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ค์น
yarn add react-virtualized
import TodoListItem from "./TodoListItem";
import "./TodoList.scss";
import React, { useCallback } from "react";
import { List } from "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);
import {
MdCheckBoxOutlineBlank,
MdRemoveCircleOutline,
MdCheckBox,
} from "react-icons/md";
import "./TodoListItem.scss";
import cn from "classnames";
import React from "react";
const TodoListItem = ({ todo, onRemove, onToggle, style }) => {
const { id, text, checked } = todo;
return (
<div className="TodoListItem-virtualized" style={style}>
<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>
</div>
);
};
export default React.memo(TodoListItem);
'JavaScript > React' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[React] SPA ๋? (0) | 2021.11.08 |
---|---|
[React] Hooks ์ ๋ฆฌ (0) | 2021.10.26 |
[React] ์ปดํฌ๋ํธ ์์๋ณด๊ธฐ (0) | 2021.10.26 |
[React] ๊ธ์ฐ๊ธฐ ๊ธฐ๋ฅ ๊ตฌํํ๊ธฐ (0) | 2021.10.22 |
[React] Redux ํด๋ ๊ตฌ์กฐ ์ ๋ฆฌํ๊ธฐ (0) | 2021.10.21 |
๋๊ธ