0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

B2BエンジニアがT3 Stackに入門してみたAdvent Calendar 2022

Day 10

t3-stack入門 (8) TodoフォームにUpdateモードを追加する

Posted at

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} />
         ))}

ここまでの変更は以下の通りです。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?