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
checked
prop to a form field without anonChange
handler. This will render a read-only field. If the field should be mutable usedefaultChecked
. Otherwise, set eitheronChange
orreadOnly
.
체크박스 뿐 아니라 체크박스가 포함된 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;