Back
Syntax
Study
Editor
Mode:
HTML
CSS
JavaScript
PHP
Reset
Run »
HTML / CSS / JS
// 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> ); }
Result
Open