[REACT] todolist 만들기
학습일 : 2023. 04. 18
이제 todolist를 본격적으로 만들어보도록 하자.
타입스크립트에게 toDo가 어떻게 생겼는지 알려주기 위한 인터페이스를 먼저 작성한다.
toDoState는 toDo들의 배열이라는 것을 알려주도록 하겠다.
category는 'DONE', 'DOING', 'TODO'만 받을 수 있다고 알려주도록 한다.
이제 ToDo를 만들면 모든 string이 아닌, 명시된 3개 중 하나의 string만을 가져야 한다.
interface IToDo {
text: string;
// id도 적어줌
id: number;
category: "TODO" | "DOING" | "DONE";
}
이제 atom의 type이 ToDo의 배열임을 알려주도록 하자.
atom<IToDo[]> 를 작성해준다.
const toDoState = atom<IToDo[]>({
key: "toDo",
default: [],
});
이제 타입스크립트는 toDos가 IToDo 객체로 이뤄진 배열임을 알게되었다.
const [toDos, setToDos] = useRecoilState(toDoState);
이제 하고자 하는 것은 폼이 제출되고 데이터가 모두 유효하다면,
state(상태)를 바꿀 것이다.
여기서 state를 바꿔줄 것이다.
const handleValid = ({ toDo }: IForm) => {
setToDos((oldToDos) => [
// id를 써줌
{ text: toDo, category: "TODO", id: Date.now() },
...oldToDos,
]);
setValue("toDo", "");
};
setToDos 함수는 두개의 동작을 할 수 있다.
1. state를 직접적으로 설정해 줄 수도 있고,
2. 다른 함수를 받을 수도 있다.
() 안에 함수를 쓴다면, 함수의 리턴값이 새로운 state가 될 것이다.
이전의 state를 oldToDos로 받아서 배열을 반환해줄 것이다.
그렇게 되면 이 배열은 oldToDos의 모든 요소를 가지게 된다.
보다시피 oldToDos는 배열이다.
setToDos((oldToDos) => [oldToDos]);
이런 방식으로 하면 배열안에 배열이 들어가버린 꼴이 되므로 안되고
내가 원하는 건 oldToDo의 요소들이 들어있는 배열을 반환해야 하므로
setToDos((oldToDos) => [...oldToDos]); 로 써준다.
이것은 배열안의 요소를 반환하게 된다.
지금까지를 보면 단순히 oldToDo를 받아서 oldToDo를 반환한다.
내가 해야 할 것은 새로운 ToDo를 넣어주는 것이다.
따라서 안에 객체를 만들고
우리의 데이터는 data.toDo에 있고,
data는 react-hook-form에서 넘어온다.
그리고 이 data.toDo는 밑에 있는 input에서 온 것이다.
{text:toDo} 를 써주면서 이제 text를 사용한다고 말해 줄 것이다.
새로운 ToDo의 text는 toDo로부터 오는 것이다.
그리고 카테고리도 작성해준다.
모든 ToDo를 TODO로부터 시작할 것이기 때문에 TODO로 적어준다.
전체 코드
<ToDoList.tsx>
import { useForm } from "react-hook-form";
import {
atom,
useRecoilState,
useRecoilValue,
useSetRecoilState,
} from "recoil";
const toDoState = atom<IToDo[]>({
key: "toDo",
default: [],
});
interface IToDo {
text: string;
id: number;
category: "TODO" | "DOING" | "DONE";
}
interface IForm {
toDo: string;
}
function ToDoList() {
const [toDos, setToDos] = useRecoilState(toDoState);
const { register, handleSubmit, setValue } = useForm<IForm>();
const handleValid = ({ toDo }: IForm) => {
setToDos((oldToDos) => [
{ text: toDo, category: "TODO", id: Date.now() },
...oldToDos,
]);
setValue("toDo", "");
};
console.log(toDos);
return (
<div>
<h1>Thorn To Do</h1>
<hr />
<form onSubmit={handleSubmit(handleValid)}>
<input
{...register("toDo", {
required: "please write a to do",
})}
placeholder="오늘 해야할 일을 입력하세요"
/>
<button>add</button>
</form>
<ul>
{toDos.map(toDo => <li key={toDo.id}>{toDo.text}</li>)}
</ul>
</div>
);
}
export default ToDoList;
결과
다음 글에 계속...:>