status1 form에서 입력
1-1. form 태그 필요(submit으로 입력 정보를 넘겨 받아야 하기 때문)
1-2. todo내용인 text를 입력한 input창 필요
1-3. 내용을 submit으로 넘길 버튼 역할을 할 input창이 필요
status2 입력 text를 받아서 submit으로 넘김
2-1. text input에 입력(todo[]에 들어갈 내용 입력)
2-2. 추가버튼을 누름(submit 형식)
status3 배열형식의 todo[]에 저장
3-1. todo[]에 최신 상태로 입력한 내용을 계속해서 const todo=["할일1", "할일2",...,"최신추가"]로 추가됨
// todo리스트의 상태를 관리할 useState필요
const [todo, setTodo] = useState([]);
useState의 상태관리 원리
<form
onSubmit={(e) => {
e.preventDefault();
handleSubmit(e.target.todo.value);
e.target.todo.value = "";
}}
>
<input
type="text"
placeholder="Add a todo"
name="todo"
autocomplete="off"
/>
<input type="submit" value="+" />
</form>
form submit으로 작성한 내용을 넘겨주기 위함
onSubmit 이벤트 핸들러를 사용
const handleSubmit = (todoText) => {
setTodo([
...todo,
{
todoText: todoText,
todoId: todoId,
todoDone: false,
},
]);
setTodoId(todoId + 1);
};
handleSubmit이 하는 일: 입력값을 todoText로 받아와서, todoText를 이용해 객체를 생성해서 저장
//고유한 식별자를 지정하기 위한 todoId로 상태관리
const [todoId, setTodoId] = useState(0);
list형식으로 배열에 저장된 내용들이 출력됨
<ul>
{todo.map((item, index) => {
return (
<li key={index}>
<span>
{item.todoText}
</span>
...생략...
</li>
);
})}
</ul>
배열이름.map((item, index) => {
return 반환
})
list항목을 누르면 할 일 완료처리 가능
<span
onClick={() => {
handleToggle(item.todoId);
}}>
{item.todoText}
</span>
const handleToggle = (todoId) => {
setTodo(
todo.map((item, index) => {
return item.todoId === todoId
? { ...item, todoDone: !item.todoDone }
: item;
})
);
};
button을 누르면 todo[]에 해당 요소가 삭제됨
<button
onClick={() => {
handleDelete(item.todoId); }} >
del
</button>
삭제 버튼을 생성
const handleDelete = (todoId) => {
setTodo(
todo.filter((item) => {
return item.todoId !== todoId;
})
);
};
useEffect(() => {
localStorage.setItem("todo", JSON.stringify(todo));
}, [todo]);
useEffect(() => {
const defaultTodo = JSON.parse(localStorage.getItem("todo"));
if (!defaultTodo) return;
setTodo(defaultTodo);
if (defaultTodo.length !== 0) {
setTodoId(defaultTodo[defaultTodo.length - 1].todoId + 1);
}
}, []);
hover 효과를 통해 동적인 느낌을 줌
transition으로 자연스러운 느낌을 줌
타이틀 부분
submit(+)버튼 부분
todo list부분