[React로 My To Do List 만들기!]
- 구현해야 할 기능
- Todo 추가하기
- Todo 삭제하기
- Todo 완료상태 변경하기 (완료 <-> 진행중)
- 요구사항
- 제목과 내용을 입력하고
추가하기
버튼 클릭하면 Working에 새로운 Todo가 추가되고 제목, 내용 input은 빈 값으로 바뀐다.- Todo의 isDone 상태가 true이면, 버튼의 라벨을
취소
, isDone 상태가 false 이면 버튼의 라벨을완료
로 조건부 렌더링 한다.- Todo의 상태가 working이면 위쪽에 위치하고, done이면 아래쪽에 위치하도록 구현한다.
- Layout의 최대 넓이는 1200px, 최소 넓이는 800px로 제한하고 전체 화면의 가운데로 정렬한다.
vanilla javascript로 to-do list를 구현했다면 다소 복잡하게 코드가 작성되었을 텐데, (추가할 때 todo 를 그려주고, 삭제할 때는 해당하는 li 태그를 찾아 remove 하고.. ) 리액트를 사용하니 todos 라는array에 [{id: 0, title: “”, body: “”, isDone: false}]
와 같은 객체를 넣어서 관리하니 , toDos가 바뀔 때마다 (setTodos가 실행될 때마다) 리렌더링 되어서 더 쉽게 구현할 수 있었던 것 같다.
오늘 오전 9시에 개인 과제가 주어졌는데, 기능적인 부분은 사실 오전에 다 완성했다!
(깜찍한 디자인으로 완성하고 싶었으나 나의 미적 감각으로는 저게 맥시멈이지 않을까..)
일단 App.jsx에 돌아가도록 다 작성하고, 이후에 컴포넌트를 분리했는데 분리하는 과정에서 약간의 오류가 생겨서 그걸 하나씩 해결해 나가는 재미도 있었다.
warning은 error와 달라서 무시해도 작동은 하지만, 매우 거슬린다. 훗날 문제가 될 지도 모르니 고쳐보자.🛠️
Warning: A component is changing an uncontrolled input to be controlled. This is likely caused by the value changing from undefined to a defined value, which should not happen. Decide between using a controlled or uncontrolled input element for the lifetime of the component.
경고: 구성 요소가 제어되지 않는 입력을 제어하도록 변경하고 있습니다. 이는 값이 정의되지 않은 값에서 정의된 값으로 변경되어 발생할 수 있으므로 발생하지 않아야 합니다. 구성 요소의 수명 동안 제어 또는 제어되지 않은 입력 요소를 사용할 것인지 결정합니다.
이 warning은 input 의 value가 처음에 undefined
일 때 주로 발생한다.
input의 value는 title이라는 state와 연결되어 있다.
그리고 onChange 이벤트가 발생할 때마다 setTitle을 통해 title을 변경하여 value로 지정한다.
const [title, setTitle] = useState(); // 초기값 없음
<input
value={title} // value를 title로 지정
onChange={(e) => setTitle(e.target.value)}
id="title"
type="text"
placeholder="Write your to do title"
required
maxLength={20}
/>
input의 value를 ||
(or)연산자로 title이 undefined일 때 공백(""
)으로 지정한다.
const [title, setTitle] = useState();
<input
value={title || ""} // 이렇게
onChange={(e) => setTitle(e.target.value)}
id="title"
type="text"
placeholder="Write your to do title"
required
maxLength={20}
/>
useState()를 사용할 때 초기값을 공백(""
)으로 지정해준다.
const [title, setTitle] = useState(""); // 이렇게
<input
value={title}
onChange={(e) => setTitle(e.target.value)}
id="title"
type="text"
placeholder="Write your to do title"
required
maxLength={20}
/>
Warning: Each child in a list should have a unique "key" prop.
목록의 각 자식은 고유한 "키" 를 가져야 한다.
이 warning은 map 메서드를 활용하여 여러 요소를 반복적으로 생성할 때 주로 발생한다.
여기서는 Todo라는 컴포넌트를 map 메서드를 통해 반복적으로 생성하고 있는데, 반복적으로 생성되는 요소에 unique한 key값을 주어야 이 warning이 사라지게 된다.
<ul className="todo-list">
{todos
.filter((todo) => todo.isDone === false)
.map((todo) => (
<Todo todo={todo} todos={todos} setTodos={setTodos}>
완료
</Todo>
))}
</ul>
<ul className="todo-list">
{todos
.filter((todo) => todo.isDone === false)
.map((todo) => (
<Todo key={todo.id} todo={todo} todos={todos} setTodos={setTodos}> // 여기서 Key 지정
완료
</Todo>
))}
</ul>
(훗날 위 코드는 TodoList라는 컴포넌트를 분리하게 되면서 변경됩니다..ㅎ)
👉 https://todo-list-theta-ebon.vercel.app/
느낀 점
컴포넌트를 분리하여 관리하니 레고 조립하는 것 같기도 하고 뚝딱뚝딱 만들어가는 재미가 있다.
state가 바뀔 때마다 rerendering되는 게 정말 편한 것 같다. (리액트의 파워💪)튜터님 리뷰