TodoEditにUpdateモードを追加
今のままだと、一度追加したTodoを更新することができませんので、TodoフォームにUpdateモードを追加することにします。
import { trpc } from "../../utils/trpc";
+type Props = {
+ editingTodo: {
+ id: number | null;
+ title: string;
+ description: string;
+ };
+};
-const TodoEdit = () => {
+const TodoEdit: FC<Props> = ({ editingTodo }) => {
const utils = trpc.useContext();
const form = useForm({
- initialValues: { title: "", description: "" },
+ initialValues: {
+ id: null as number | null,
+ title: "",
+ description: "",
+ },
validate: zodResolver(createTodoSchema),
});
+ useEffect(() => {
+ form.setValues(editingTodo);
+ }, [editingTodo]);
+
const createTodo = trpc.todo.create.useMutation({
Update対象のTodoのデータを受け取るようにします。受け取ったTodoのデータが変化していたなら、
Update対象が変わったということなので、form.setValuesでTodoのデータをフォームにセットします。
});
+ const updateTodo = trpc.todo.update.useMutation({
+ onSettled: () => {
+ utils.todo.getAll.invalidate();
+ },
+ });
return (
<form
onSubmit={form.onSubmit((data) => {
- createTodo.mutate(data);
+ if (data.id) {
+ updateTodo.mutate({
+ id: data.id,
+ title: data.title,
+ description: data.description,
+ });
+ } else {
+ createTodo.mutate(data);
+ }
form.reset();
})}
>
todoのidがnullならAdd、そうでなければUpdateします。
/>
- <Button type="submit" mt="sm">
- New Task
- </Button>
+ <Group className="">
+ <Button type="reset" mt="sm" onClick={form.reset}>
+ Reset
+ </Button>
+ <Button type="submit" mt="sm">
+ {form.values.id ? "Update Task" : "New Task"}
+ </Button>
+ </Group>
</form>
モードに合わせてButtonのラベルを変えることにします。
TodoItemにUpdateボタンを追加
TodoItemにUpdateボタンを追加します。押されたときに実行される関数はProp経由で親コンポーネントから渡すようにします。
import Link from "next/link";
+type EditingTodo = {
+ id: number | null;
+ title: string;
+ description: string;
+};
type Props = {
todo: TodoEntry;
+ setEditingTodo: (editingTodo: EditingTodo) => void;
};
-const TodoItem: FC<Props> = ({ todo }) => {
+const TodoItem: FC<Props> = ({ todo, setEditingTodo }) => {
const { data: sessionData } = useSession();
const utils = trpc.useContext();
@@ -27,15 +33,26 @@ const TodoItem: FC<Props> = ({ todo }) => {
</Link>
</Text>
{sessionData?.user?.id === todo.owner.id && (
- <ActionIcon
- onClick={() => {
- deleteTodo.mutate({ id: todo.id });
- }}
- color={"red"}
- variant={"transparent"}
- >
- <Trash />
- </ActionIcon>
+ <Group>
+ <ActionIcon
+ onClick={() => {
+ deleteTodo.mutate({ id: todo.id });
+ }}
+ color={"red"}
+ variant={"transparent"}
+ >
+ <Trash />
+ </ActionIcon>
+ <ActionIcon
+ onClick={() => {
+ setEditingTodo(todo);
+ }}
+ color={"red"}
+ variant={"transparent"}
+ >
+ <Pencil />
+ </ActionIcon>
+ </Group>
)}
</Group>
</Card>
Update対象Todoの情報を格納するStateを追加
Update対象Todoの情報を格納するStateを追加し、TodoEditにそのStateを渡します。
TodoItemにそのStateを変更する関数を渡します。
import TodoItem from "../features/todo/item";
+import { useState } from "react";
const Todo: NextPage = () => {
+ const [editingTodo, setEditingTodo] = useState({
+ id: null as number | null,
+ title: "",
+ description: "",
+ });
const todos = trpc.todo.getAll.useQuery();
return (
<Layout title="Todo">
<h1 className="">Todo</h1>
<AuthShowcase />
- <TodoEdit />
+ <TodoEdit editingTodo={editingTodo} />
<div>
{todos.data?.map((todo) => (
- <TodoItem key={todo.id} todo={todo} />
+ <TodoItem key={todo.id} todo={todo} setEditingTodo={setEditingTodo} />
))}
ここまでの変更は以下の通りです。