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

## TodoEditにUpdateモードを追加

今のままだと、一度追加したTodoを更新することができませんので、TodoフォームにUpdateモードを追加することにします。
```diff_typescript
 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のデータをフォームにセットします。
```diff_typescript
   });
+  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します。
```diff_typescript
       />
-      <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経由で親コンポーネントから渡すようにします。

```diff_typescript
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を変更する関数を渡します。

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

```

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

https://github.com/bioflowy/t3-todo-example/commit/5f5a26f9d8d7d297c4b976f5637cabaf44202e18