[TIL] React로 간단한 Todo 앱 만들기 - 2

Alex J. Lee·2021년 9월 28일
0

TIL

목록 보기
22/58

수정사항

input에 입력한 값을 제출 버튼을 눌렸을 때 뿐만 아니라 Enter를 눌렸을 때도 todo list에 추가하기 위해 현재 inputonKeyDown 이벤트 핸들러, buttononClick 이벤트 핸들러가 각각 달려 있다. inputbuttonform 태그로 감싸고 form 에다 onSubmit 이벤트 핸들러를 하나만 달아도 똑같은 효과를 낼 수 있다.

App.js

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 an onChange handler. This will render a read-only field. If the field should be mutable use defaultChecked. Otherwise, set either onChange or readOnly.

체크박스 뿐 아니라 체크박스가 포함된 li 전체를 클릭했을 때 handleCheckbox가 실행되도록 하였더니 위와 같은 에러 메시지가 떴다. 에러를 해결하기 위해서는 다음 세 가지 해결 방안 중 하나를 상황에 맞게 적용해야 한다.

  1. 체크박스에 onChange 이벤트 핸들러를 달아준다.
  2. readOnly를 사용한다.
  3. checked 대신 defaultChecked를 사용한다.

onChange 이벤트 핸들러를 달지는 않을 것이고, defaultChecked도 적절하지 않기 때문에 체크박스에 readOnly 속성을 추가해 주었다. checked 속성을 자바스크립트가 li가 클릭될 때마다 바꾸어 주고 있기 때문에 readOnly를 사용해도 클릭 시 체크박스가 토글되는 것을 확인할 수 있다.

TodoItem.js

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;
profile
🦄✨글 잘 쓰는 개발자가 되기 위해 꾸준히 기록합니다 ✨🦄

0개의 댓글