🙆♀️
【NextJs14】NextJs14 と 便利なライブラリ【#31Create Todo Server Actions】
【#31Create Todo Server Actions】
YouTube: https://youtu.be/iVyydLPOfIQ
今回はTodoを作成する関数を作成します。
こちらはNextJsのServerActionsを使用します。
まずは、下記ファイルの
isCompletedのデフォルトの値を設定します。
prisma/schema.prisma
// This is your Prisma schema file,
// learn more about it in the docs: https://pris.ly/d/prisma-schema
generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
directUrl = env("DIRECT_URL")
}
model Todo {
id String @id @default(cuid())
title String
isCompleted Boolean @default(false)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
npx prisma generate
npx prisma db push
もしうまくいかない場合は
npx prisma migrate reset
を先に実行してデータベースを
初期化してみてください。
actions/todo-create
"use server";
import * as z from "zod";
import { CreateTodoSchema } from "@/types/schema";
import { db } from "@/lib/db";
import { revalidatePath } from "next/cache";
import { auth } from "@clerk/nextjs";
export const CreateTodo = async (values: z.infer<typeof CreateTodoSchema>) => {
const { userId } = auth();
if (!userId) {
return {
error: "Unauthorized",
};
}
const validatedFields = CreateTodoSchema.safeParse(values);
if (!validatedFields.success) {
return {
error: "Invalid fields",
};
}
const { title } = validatedFields.data;
const todo = await db.todo.create({
data: {
title,
},
});
console.log(todo);
revalidatePath("/account");
return { success: "New todo created!" };
};
app/(main)/account/_components/todo-form.tsx
"use client";
import { useTransition } from "react";
import * as z from "zod";
import { useForm } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod";
import { CreateTodo } from "@/actions/todo-create";
import { CreateTodoSchema } from "@/types/schema";
import {
Form,
FormControl,
FormField,
FormItem,
FormMessage,
} from "@/components/ui/form";
import { Input } from "@/components/ui/input";
import { Button } from "@/components/ui/button";
import { toast } from "sonner";
export const TodoForm = () => {
const [isPending, startTransition] = useTransition();
const form = useForm<z.infer<typeof CreateTodoSchema>>({
resolver: zodResolver(CreateTodoSchema),
defaultValues: {
title: "",
},
});
const onSubmit = (values: z.infer<typeof CreateTodoSchema>) => {
startTransition(() => {
CreateTodo(values)
.then((data) => {
toast.success(data.success);
})
.catch((data) => {
if (data) {
toast.error(data.error);
} else {
toast.error("Something went wrong!");
}
});
});
};
return (
<Form {...form}>
<form
onSubmit={form.handleSubmit(onSubmit)}
className="flex items-center gap-x-1 w-full max-w-xl"
>
<FormField
control={form.control}
name="title"
render={({ field }) => (
<FormItem className="w-full">
<FormControl>
<Input
{...field}
disabled={isPending}
type="text"
placeholder="Enter your todo"
/>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<Button type="submit" disabled={isPending} variant="primary">
Create
</Button>
</form>
</Form>
);
};
Discussion