Next.js
Beginner
1 min read
Mutations with Server Actions
Example
// app/todos/actions.ts
'use server';
import { revalidatePath } from 'next/cache';
import { db } from '@/lib/db';
export async function createTodo(formData: FormData) {
const title = formData.get('title') as string;
if (!title || title.trim().length === 0) {
return { error: 'Title is required' };
}
await db.todo.create({ data: { title: title.trim() } });
revalidatePath('/todos'); // refresh the todos list
return { success: true };
}
export async function deleteTodo(id: string) {
await db.todo.delete({ where: { id } });
revalidatePath('/todos');
}
// app/todos/NewTodoForm.tsx
'use client';
import { useFormState, useFormStatus } from 'react-dom';
import { createTodo } from './actions';
function SubmitButton() {
const { pending } = useFormStatus();
return (
<button type="submit" disabled={pending}>
{pending ? 'Adding...' : 'Add Todo'}
</button>
);
}
export default function NewTodoForm() {
const [state, formAction] = useFormState(createTodo, null);
return (
<form action={formAction}>
<input name="title" type="text" placeholder="New todo..." />
{state?.error && <p className="text-red-500">{state.error}</p>}
<SubmitButton />
</form>
);
}