하루 하나씩 작성하는 TIL #24
이전 피드백에서 파일을 세분화 할 필요성이 있다고 느껴 css는 제외하고 파일을 구조화 하였다.
App.jsx
에 붙여주기form
태그와 input
태그로 화면 구성하기button
태그 만들기TodoContainer의 데이터를 변경하는 이벤트를 등록합시다
id
를 사용하세요!filter
메서드를 사용하세요!id
를 사용하세요!map
메서드를 사용하세요!yarn add react-router-dom
yarn create vite 폴더명 --template react
cd 폴더명
yarn
yarn dev
git init
git remote add origin 내 레포지 링크
git add .
git commit -m "커밋 메세지"
git push -u origin master
순으로 레포지에 틀을 올려주고 ,
src폴더 안에 components라는 폴더를 만들어주고, 그 안에
Layout.jsx
components안에 todo라는 폴더를 만들어주고, 그 안에
TodoContainer.jsx
TodoForm.jsx
TodoItem.jsx
Todolist.jsx
이렇게 4가지를 만들어 준다.
import { useState } from "react";
import TodoForm from "./TodoForm";
import TodoList from "./TodoList";
const TodoContainer = () => {
const [todos, setTodos] = useState([
{
id: 1,
title: "할 일 1",
content: "할 일 1 내용",
isDone: false,
},
]);
//useState 훅을 사용하여 todos 상태와 setTodos 함수를 생성, 할일 목록을 관리
const workingTodos = todos.filter((todo) => !todo.isDone);
const doneTodos = todos.filter((todo) => todo.isDone);
//todos 배열을 이용하여 작업 중인 할 일과 완료된 할 일 필터링, 할당.
return (
<section>
<h1 className="title">Todo</h1>
<TodoForm setTodos={setTodos} />
<TodoList title="Working" todos={workingTodos} setTodos={setTodos} />
<TodoList title="Done" todos={doneTodos} setTodos={setTodos} />
</section>
);
};
//<TodoForm> 컴포넌트를 렌더링.
//이 컴포넌트에는 setTodos 함수가 props로 전달.
export default TodoContainer;
const TodoForm = ({ setTodos }) => {
const onSubmit = (e) => {
e.preventDefault();
const formData = new FormData(e.target);
const title = formData.get("title");
const content = formData.get("content");
if (!title.trim() || !content.trim())
return alert("제목과 내용을 입력해주세요.");
const nextTodo = {
id: crypto.randomUUID(),
title,
content,
isDone: false,
};
setTodos((prev) => [nextTodo, ...prev]);
e.target.reset();
};
return (
<div>
<form onSubmit={onSubmit}>
<input type="text" placeholder="제목" name="title" />
<input type="text" placeholder="내용" name="content" />
<button type="submit">추가</button>
</form>
</div>
);
};
export default TodoForm;
const TodoItem = ({ todo, setTodos }) => {
const { id, title, content, isDone } = todo;
const deleteTodo = () => {
setTodos((prev) => prev.filter((todo) => todo.id !== id));
};
const toggleTodo = () => {
setTodos((prev) =>
prev.map((todo) =>
todo.id === id ? { ...todo, isDone: !todo.isDone } : todo
)
);
};
return (
<div className="todo-card">
<h3 className="todo-title">{title}</h3>
<p>{content}</p>
<div>
<button onClick={toggleTodo}>{isDone ? "취소" : "완료"}</button>
<button onClick={deleteTodo}>삭제</button>
</div>
</div>
);
};
export default TodoItem;
Todolist.jsx
import TodoItem from "./TodoItem";
const TodoList = ({ title, todos, setTodos }) => {
return (
<div>
<h2 className="todo-list-title">{title}</h2>
<ul>
{todos.map((todo) => (
<li key={todo.id}>
<TodoItem todo={todo} setTodos={setTodos} />
</li>
))}
</ul>
</div>
);
};
export default TodoList;