데이터베이스는 json-server 를 사용했다. 먼저 api 폴더를 만들어 todos > route.ts 경로에 백엔드 로직을 작성했다. toggle을 위한 patch 함수는
export async function PATCH(request: Request) {
try {
const { isDone, id } = await request.json();
await fetch(`http://localhost:4000/todos/${id}`, {
method: 'PATCH',
body: JSON.stringify({ id, isDone }),
});
return new Response('Todo State Updated', { status: 200 });
} catch (error) {
console.error(`Error`, error);
return new Response('Server Error :(', { status: 500 });
}
}
이런식으로 작성해줬는데 클라이언트로부터 받은 요청의 바디에서 Todo 항목의 완료 여부와 ID를 추출하고, 해당 ID를 가진 Todo 항목의 상태를 업데이트하는 역할을 한다.
이제 todoList 컴포넌트로 넘어가서
Todo 항목의 완료 여부를 토글하는 기능을 구현했다.
const toggleIsDoneHandler = (id: string, isDone: boolean) => {
const updatedTodo = {
id: id,
isDone: !isDone
};
isDoneMutation.mutate(updatedTodo, {
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ['todos'] });
}
});
};
const isDoneMutation = useMutation({
mutationFn: async (updatedTodo: UpdateTodo) => {
try {
await fetch(`http://localhost:3000/api/todos`, {
method: 'PATCH',
body: JSON.stringify({ id: updatedTodo.id, isDone: updatedTodo.isDone })
});
} catch (error) {
console.log('error', error);
}
}
});
코드를 살펴보면
toggleIsDoneHandler : 이 함수는 Todo 항목의 ID와 현재 완료 여부를 매개변수로 받고 이 정보를 이용하여 업데이트할 Todo 항목을 결정해준다. 완료 여부를 토글하기 위해 받은 완료 여부를 반대값으로 설정한다.
isDoneMutation: isDoneMutation은 Todo 항목의 완료 여부를 업데이트하는데 사용된다. toggleIsDoneHandler에 의해 호출되고, Todo 항목의 완료 여부가 변경될 때마다 실행된다.
서버로 PATCH 요청을 보내서 Todo 항목의 상태를 업데이트하고 요청이 성공하면 onSuccess 콜백 함수가 실행되어 invalidateQuerie 를 통해 캐시를 무효화하고 새로운 데이터를 다시 불러온다.
그리고 updatedTodo: UpdateTodo 이부분에서 UpdateTodo 의 타입은
export type UpdateTodo = Omit<Todos, 'title' | 'content'>;
이런식으로 작성하고 import 해서 사용해줬다.
마지막으로 toggle을 위한 버튼을 만들어줘야 했는데 평소처럼 완료: 취소 버튼을 할까 하다가 이번에는 체크박스로 하면 시각적으로 항목의 완료상태를 빠르게 확인할수도 있겠다는 생각이 들어 체크박스로 만들어줬다.
<input
type="checkbox"
checked={todo.isDone}
onChange={() => toggleIsDoneHandler(todo.id, todo.isDone)}
className="form-checkbox h-5 w-5 text-green-500 rounded"
/>