ν μ ν¬κΈ°λ‘ μλΌ λ¨Ήλ 리μ‘νΈ μΉμ 11 - μ΅μ ν
μΉ μλΉμ€μ μ±λ₯μ κ°μ νλ λͺ¨λ νμλ₯Ό μΌμ»«λ λ§μ΄λ€.
λ©λͺ¨λ¦¬μ μ΄μ (κ²°κ³Όκ°μ μ μ₯νμ¬ κΈ°μ΅) κΈ°λ²μ κΈ°λ°μΌλ‘ λΆνμν μ°μ°μ μ΅μ ννλ 리μ‘νΈ ν μ΄λ€.
import "./List.css";
import TodoItem from "./TodoItem";
import { useState, useMemo } from "react";
const List = ({ todos, onUpdate, onDelete }) => {
const [search, setSearch] = useState("");
const onChangeSearch = (e) => {
setSearch(e.target.value);
};
const getFilteredData = () => {
if (search === "") {
return todos;
}
return todos.filter((todo) =>
todo.content.toLowerCase().includes(search.toLowerCase())
);
};
const filteredTodos = getFilteredData();
const { totalCount, doneCount, notDoneCount } = useMemo(() => {
const totalCount = todos.length;
const doneCount = todos.filter((todo) => todo.isDone).length;
const notDoneCount = totalCount - doneCount;
return { totalCount, doneCount, notDoneCount };
}, [todos]);
return (
<div className="List">
<h4>Todo List π±</h4>
<div>
<div>total: {totalCount}</div>
<div>done: {doneCount}</div>
<div>notDone: {notDoneCount}</div>
</div>
<input
value={search}
onChange={onChangeSearch}
placeholder="κ²μμ΄λ₯Ό μ
λ ₯νμΈμ"
/>
<div className="todos_wrapper">
{filteredTodos.map((todo) => (
<TodoItem
key={todo.id}
{...todo}
onUpdate={onUpdate}
onDelete={onDelete}
/>
))}
</div>
</div>
);
};
export default List;
List.jsxμ μ½λλ₯Ό μμ±νμλ€.getAnalyzedDataκ° λΆνμνκ² μ°μ°λλκ²μ λ§κΈ° μν΄useMemoλ₯Ό μ¬μ©νμλ€.

μ»΄ν¬λνΈλ₯Ό μΈμλ‘ λ°μ, μ΅μ νλ μ»΄ν¬λνΈλ‘ λ§λ€μ΄ λ°ννλ κ²
μ¦, λΆλͺ¨ μ»΄ν¬λνΈκ° 리λ λλ§μ΄ λλλΌλ μμ μ΄ λ°λ propsκ° λ°λμ§ μμΌλ©΄ λ€μ 리λ λλ§μ΄ λ°μνμ§ μλλ‘ λ©λͺ¨μ΄μ μ΄μ
μ΄ λκΈ° λλ¬Έμ λΆνμν 리λ λλ§μ΄ λ°©μ§λμ΄μ μλμΌλ‘ μ΅μ νκ° μ΄λ£¨μ΄μ§κ² λκ² νλ κ²μ΄λ€.
import "./Header.css";
import { memo } from "react";
const Header = () => {
return (
<div className="Header">
<h3>μ€λμ π </h3>
<h1>{new Date().toDateString()}</h1>
</div>
);
};
const memoizedHeader = memo(Header);
export default memoizedHeader; //window + . λ‘ μ΄λͺ¨μ§ μΆκ° κ°λ₯νλ€.
Headerμ»΄ν¬λνΈκ° λΆνμνκ² λ¦¬λ λλ§ λλ λ¬Έμ μ μ ν΄κ²°ν μ μλ€.
κΈ°λ₯ λ¨Όμ ꡬννκ³ μ΅μ νλ λμ€μ νλ κ²μ κΆμ₯
μ΅μ νκ° νμν λΆλΆλ§ νκΈ° (λͺ¨λ λΆλΆμ λΆνμ)
import "./TodoItem.css";
import { memo } from "react";
const TodoItem = ({ id, isDone, content, date, onUpdate, onDelete }) => {
const onChangeCheckbox = () => {
onUpdate(id);
};
const onClickDeleteButton = () => {
onDelete(id);
};
return (
<div className="TodoItem">
<input
onChange={onChangeCheckbox}
readOnly
checked={isDone}
type="checkbox"
/>
<div className="content">{content}</div>
<div className="date">{new Date(date).toLocaleDateString()}</div>
<button onClick={onClickDeleteButton}>μμ </button>
</div>
);
};
export default memo(TodoItem);
import "./App.css";
import { useState, useRef, useReducer, useCallback } from "react";
import Header from "./components/Header";
import Editor from "./components/Editor";
import List from "./components/List";
const mockData = [
{
id: 0,
isDone: false,
content: "React 곡λΆνκΈ°",
date: new Date().getTime(),
},
{
id: 1,
isDone: false,
content: "μ½μ΄νμ κ°κΈ°",
date: new Date().getTime(),
},
{
id: 2,
isDone: false,
content: "μΌμ° μΌμ΄λκΈ°",
date: new Date().getTime(),
},
];
function reducer(state, action) {
switch (action.type) {
case "CREATE":
return [action.data, ...state];
case "UPDATE":
return state.map((item) =>
item.id === action.targetId ? { ...item, isDone: !item.isDone } : item
);
case "DELETE":
return PopStateEvent.filter((item) => item.id !== action.targetId);
default:
return state;
}
}
function App() {
const [todos, dispatch] = useReducer(reducer, mockData);
const idRef = useRef(3);
const onCreate = useCallback((content) => {
dispatch({
type: "CREATE",
data: {
id: idRef.current++,
isDone: false,
content: content,
date: new Date().getTime(),
},
});
}, []);
const onUpdate = useCallback((targetId) => {
dispatch({
type: "UPDATE",
targetId: targetId,
});
}, []);
const onDelete = useCallback((targetId) => {
dispatch({
type: "DELETE",
targetId: targetId,
});
}, []);
return (
<div className="App">
<Header />
<Editor onCreate={onCreate} />
<List todos={todos} onUpdate={onUpdate} onDelete={onDelete} />
</div>
);
}
export default App;
App.jsxμTodoItem.jsxμ½λμ΄λ€.