
input에 입력한 값을 제출 버튼을 눌렸을 때 뿐만 아니라 Enter를 눌렸을 때도 todo list에 추가하기 위해 현재 input에 onKeyDown 이벤트 핸들러, button에 onClick 이벤트 핸들러가 각각 달려 있다. input과 button을 form 태그로 감싸고 form 에다 onSubmit 이벤트 핸들러를 하나만 달아도 똑같은 효과를 낼 수 있다.
function App() {
const [task, setTask] = useState("");
const [todoList, setTodoList] = useState([]);
const handleInputText = (event) => {
setTask(event.target.value);
};
// handleAddBtn, handleKeyDown을 handleSubmit하나로 합침
const handleSubmit = (event) => {
event.preventDefault();
const todo = {
id: nanoid(),
isChecked: false,
task: task,
};
setTodoList([todo, ...todoList]);
setTask("");
console.log(todo);
};
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과 button을 form으로 감싸고 form에 onSubmit이벤트 핸들러 추가 */}
<form onSubmit={handleSubmit}>
<input
className="task-input-text"
value={task}
type="text"
placeholder="Add task"
onChange={handleInputText}
/>
<button className="task-input-btn">
<i className="fas fa-plus"></i>
</button>
</form>
</div>
<div>
<ul>
{todoList.map((el) => (
<TodoItem
todo={el}
handleCheckbox={handleCheckbox}
handleDeleteBtn={handleDeleteBtn}
/>
))}
</ul>
</div>
</main>
</div>
);
}
export default App;
Warning: You provided a
checkedprop to a form field without anonChangehandler. This will render a read-only field. If the field should be mutable usedefaultChecked. Otherwise, set eitheronChangeorreadOnly.
체크박스 뿐 아니라 체크박스가 포함된 li 전체를 클릭했을 때 handleCheckbox가 실행되도록 하였더니 위와 같은 에러 메시지가 떴다. 에러를 해결하기 위해서는 다음 세 가지 해결 방안 중 하나를 상황에 맞게 적용해야 한다.
onChange 이벤트 핸들러를 달아준다.readOnly를 사용한다.checked 대신 defaultChecked를 사용한다.onChange 이벤트 핸들러를 달지는 않을 것이고, defaultChecked도 적절하지 않기 때문에 체크박스에 readOnly 속성을 추가해 주었다. checked 속성을 자바스크립트가 li가 클릭될 때마다 바꾸어 주고 있기 때문에 readOnly를 사용해도 클릭 시 체크박스가 토글되는 것을 확인할 수 있다.
import React from 'react';
import './TodoItem.css';
const TodoItem = ({ todo, handleCheckbox, handleDeleteBtn }) => {
return (
<li id={todo.id} onClick={() => handleCheckbox(todo.id)}>
<input type="checkbox" checked={todo.isChecked} readOnly/>
<span className={todo.isChecked ? "task-content checked" : "task-content"}>{todo.task}</span>
<button className="task-delete-btn" onClick={(event) => {
event.stopPropagation();
handleDeleteBtn(todo.id)
}}>
<i className="far fa-trash-alt"></i>
</button>
</li>
)
};
export default TodoItem;