순서
- create-react-app으로 새로운 React 프로젝트 생성
- 프로젝트 초기화 (App.js, App.css 비우기)
- 레이아웃 구상
- 재사용되는 부분을 개별 컴포넌트로 분리 (TodoItem.js)
- JSX로 문서 구조 만들기
- input과 button에 적절한 이벤트 핸들러 함수 달아주기
App.js
import React, { useState } from "react";
import { nanoid } from "nanoid";
import "./App.css";
import TodoItem from "./components/TodoItem";
function App() {
const [task, setTask] = useState("");
const [todoList, setTodoList] = useState([]);
const handleInputText = (event) => {
setTask(event.target.value);
};
const handleAddBtn = (event) => {
const todo = {
id: nanoid(),
isChecked: false,
task: task,
};
setTodoList([todo, ...todoList]);
setTask("");
};
const handleKeypress = (event) => {
if (event.key === "Enter") {
handleAddTodo();
}
}
const handleCheckbox = (id) => {
const idx = todoList.findIndex((el) => el.id === id);
const newTodoList = [...todoList];
newTodoList[idx] = {
...todoList[idx],
isChecked: !todoList[idx].isChecked,
};
setTodoList(newTodoList);
};
const handleDeleteBtn = (id) => {
const idx = todoList.findIndex((el) => el.id === id);
const newTodoList = [...todoList];
newTodoList.splice(idx, 1);
setTodoList(newTodoList);
};
return (
<div className="App">
<header>
<h1>TODO</h1>
</header>
<main>
<div className="task-input-wrapper">
<input
className="task-input-text"
value={task}
type="text"
placeholder="Add task"
onChange={handleInputText}
onKeyDown={handleKeypress}
/>
<button className="task-input-btn" onClick={handleAddBtn}>
<i className="fas fa-plus"></i>
</button>
</div>
<div>
<ul>
{todoList.map((el) => (
<TodoItem
todo={el}
handleCheckbox={handleCheckbox}
handleDeleteBtn={handleDeleteBtn}
/>
))}
</ul>
</div>
</main>
</div>
);
}
export default App;
TodoItem.js
import React from 'react';
import './TodoItem.css';
const TodoItem = ({ todo, handleCheckbox, handleDeleteBtn }) => {
return (
<li id={todo.id}>
<input type="checkbox" checked={todo.isChecked} onChange={() => handleCheckbox(todo.id)} />
<span className={todo.isChecked ? "task-content checked" : "task-content"}>{todo.task}</span>
<button className="task-delete-btn" onClick={() => handleDeleteBtn(todo.id)}><i className="far fa-trash-alt"></i></button>
</li>
)
};
export default TodoItem;