npm create vite@latest
npm i
npm run dev

import { useState } from "react";
import "./App.css";
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 App() {
const [todos, setTodos] = useState([mockData]);
return (
<div className="App">
<Header />
<Editor />
<List />
</div>
);
}
export default App;
import { useState, useRef } from "react";
import "./App.css";
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 App() {
const [todos, setTodos] = useState(mockData);
const idRef = useRef(3);
const onCreate = (content) => {
const newTodo = {
id: idRef.current++,
isDone: false,
content: content,
date: new Date().getTime(),
};
setTodos([newTodo, ...todos]);
};
return (
<div className="App">
<Header />
<Editor onCreate={onCreate} />
<List />
</div>
);
}
export default App;
import "./Editor.css";
import { useState, useRef } from "react";
const Editor = ({ onCreate }) => {
const [content, setContent] = useState("");
const contentRef = useRef();
const onChangeContent = (e) => {
setContent(e.target.value);
};
const onSubmit = () => {
if (content === "") {
contentRef.current.focus();
return;
}
onCreate(content);
setContent("");
};
const onKeydown = (e) => {
if (e.keyCode === 13) onSubmit();
};
return (
<div className="Editor">
<input
ref={contentRef}
value={content}
onChange={onChangeContent}
onKeyDown={onKeydown}
placeholder="새로운 Todo..."
/>
<button onClick={onSubmit}>추가</button>
</div>
);
};
export default Editor;
import "./List.css";
import TodoItem from "./TodoItem";
import { useState } from "react";
const List = ({ todos }) => {
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.toLocaleLowerCase())
);
};
const filteredTodos = getFilteredData();
return (
<div className="List">
<h4>Todo List 📌</h4>
<input
value={search}
onChange={onChangeSearch}
placeholder="검색어를 입력하세요"
/>
<div className="todos_wrapper">
{filteredTodos.map((todo) => {
return <TodoItem key={todo.id} {...todo} />;
})}
</div>
</div>
);
};
export default List;
return <TodoItem key={todo.id} {...todo} />;
Trouble Shooting
✅setTodos( todos.map((todo) => todo.id === targetId ? { ...todo, isDone: !todo.isDone } : todo ) );❌
setTodos( todos.map((todo) => {todo.id === targetId ? { ...todo, isDone: !todo.isDone } : todo;} ) );중괄호로 감쌀 경우 새로운 객체 생성의 의미가 되어버려 의도와 다른 코드가 된다. 주의.
...
const onDelete = (targetId) => {
// 인수 : todos 배열에서 targetId와 일치하는 id를 갖는 요소만 삭제한 새로운 배열
setTodos(todos.filter((todo) => todo.id != targetId));
};
...
<div className="App">
<Header />
<Editor onCreate={onCreate} />
<List todos={todos} onUpdate={onUpdate} onDelete={onDelete} />
</div>
...
...
const onClickDeleteButton = () => {
onDelete(id);
};
...
<button onClick={onClickDeleteButton}>삭제</button>
...