Skip to the solution
EasyFrontend8 min read

What is the next/form Form component and when would you use it?

828 views

The problem

Question presented to candidate: "We have a search box on every page that sends the user to a results page with the query in the URL. Someone suggested using the Form component from next/form instead of a plain form. What does it do differently, and when would you not use it?"

What a strong answer should cover:

  • <Form> from next/form extends the HTML <form>; it shipped with Next.js 15.
  • With a string action it behaves like a GET form: input values become search params (/search?query=abc), but Next.js performs a client-side navigation instead of a full reload, keeping layouts and client state.
  • It prefetches the target route's shared UI (layouts, loading.js) when the form is visible, so loading UI appears instantly on submit; props replace, scroll, prefetch.
  • Progressive enhancement: without JavaScript it is a normal GET form, so search still works.
  • With a function action (a Server Action) it is just a React form for mutations: no prefetch, replace and scroll ignored.
  • Not for: method="post" to an external URL, target, encType, or file inputs with a string action; use a plain <form>.

Clarifying questions expected:

  • "Is the form navigating to a URL (search, filter) or changing data (create, update)?" β€” string action versus Server Action.
  • "Should each search create a history entry?" β€” the replace prop.

Code / implementation expected: Yes β€” a search form with a string action and a results page reading searchParams.

  • nextjs
  • forms
  • navigation

Try it yourself

Sketch your approach before you read the solution. That is what the interview tests.

Stuck? Get a hint.

A short nudge toward the approach. It will not give the answer away.

Solution

The solution is hidden so you can try first

8 min read Β· 9 sections

Read the code

A search form that navigates to a results page
// app/page.tsx β€” a Server Component can render <Form> directly
import Form from "next/form";
import SearchButton from "./SearchButton";

export default function Home() {
  return (
    <Form action="/search">
      {/* Submitting navigates to /search?query=... */}
      <input name="query" placeholder="Search products" />
      <SearchButton />
    </Form>
  );
}

// app/SearchButton.tsx β€” instant feedback while the navigation is pending
"use client";
import { useFormStatus } from "react-dom";

export default function SearchButton() {
  const { pending } = useFormStatus();
  return <button type="submit">{pending ? "Searching..." : "Search"}</button>;
}

// app/search/page.tsx β€” the results page reads the query from searchParams
export default async function SearchPage({ searchParams }: PageProps<"/search">) {
  const { query = "" } = await searchParams;
  const results = await searchProducts(String(query));
  return <ul>{results.map((r) => <li key={r}>{r}</li>)}</ul>;
}

async function searchProducts(q: string) {
  return ["red shoes", "blue shoes", "red hat"].filter((p) => p.includes(q.toLowerCase()));
}

// app/search/loading.tsx β€” shown immediately on submit (prefetched with the form)
export default function Loading() {
  return <p>Loading results...</p>;
}
Form with a Server Action for a mutation
// app/posts/new/actions.ts
"use server";
import { redirect } from "next/navigation";

export async function createPost(formData: FormData) {
  const title = String(formData.get("title") ?? "");
  const id = await savePost(title);
  redirect(`/posts/${id}`);
}

async function savePost(title: string) {
  return title.toLowerCase().replace(/\s+/g, "-") || "untitled";
}

// app/posts/new/page.tsx
import Form from "next/form";
import { createPost } from "./actions";

export default function NewPost() {
  // With a function action, <Form> behaves like a React form: no URL, no prefetch
  return (
    <Form action={createPost}>
      <input name="title" />
      <button type="submit">Create post</button>
    </Form>
  );
}

Discussion

Other approaches, follow-ups and how it went in real interviews.

Sign in to join the discussion.

No comments yet. Share how you would answer it.

Question 10 of 129 in Next.js

Keep your momentum going.

Mark this question solved to track your progress, then take the next one while it is fresh.

All Next.js questions
Up nextEasy

What is the difference between the /public folder and imported assets in Next.js?

Continue