Wire Up the New and Edit Pages
Wire Up the New and Edit Pages
New contact page
Replace the placeholder in app/contacts/new/page.tsx:
import { createContactAction } from "@/lib/actions";
import ContactForm from "@/components/ContactForm";
export default function NewContactPage() {
return (
<>
<div className="page-heading">
<h1>New contact</h1>
</div>
<ContactForm action={createContactAction} submitLabel="Save contact" />
</>
);
}
createContactAction is passed straight through as the form’s action —
no wiring, no event handler.
Edit contact page
Replace the placeholder in app/contacts/[id]/edit/page.tsx:
import { notFound } from "next/navigation";
import { getContactById } from "@/lib/contacts";
import { updateContactAction } from "@/lib/actions";
import ContactForm from "@/components/ContactForm";
export const dynamic = "force-dynamic";
export default async function EditContactPage({ params }: { params: { id: string } }) {
const contact = await getContactById(params.id);
if (!contact) notFound();
const boundAction = updateContactAction.bind(null, params.id);
return (
<>
<div className="page-heading">
<h1>Edit {contact.name}</h1>
</div>
<ContactForm action={boundAction} contact={contact} submitLabel="Save changes" />
</>
);
}
updateContactAction takes two arguments — id and formData — but a
form’s action prop can only pass it one (formData, on submit). .bind(null, params.id)
creates a new function with id permanently attached, so what the form
actually calls behaves like (formData) => updateContactAction(id, formData).
This is the standard pattern for passing extra, fixed arguments into a
Server Action from a specific page.
Add Edit and Delete buttons to the detail page
Open app/contacts/[id]/page.tsx and update the detail-actions div:
<div className="detail-actions">
<Link href={`/contacts/${contact.id}/edit`} className="btn btn-ghost">Edit</Link>
<Link href="/" className="btn btn-ghost">Back to all contacts</Link>
</div>
(Delete stays out for now — it needs a Client Component, which is Module 6.)
Test it
Click “+ Add contact” in the nav bar, fill in a name and a couple of other
fields, and submit. You should land on that new contact’s detail page —
confirming both the create and the redirect worked. Go back to Home; the
new contact should appear in the list, correctly grouped by its first
letter (confirming revalidatePath("/") did its job). Now click “Edit” on
any contact, change a field, and save — you should land back on the detail
page with the updated value showing.
Checkpoint
You can create a new contact from the nav bar and edit any existing one,
using the same form component for both, with no page needing to manually
refetch or reload to see the change.