Formulario

El componente <Form> extiende el elemento HTML <form> para proporcionar precarga (prefetching) de interfaz de carga (loading UI), navegación del lado del cliente al enviar y mejora progresiva.

Es útil para formularios que actualizan parámetros de búsqueda en la URL, ya que reduce el código repetitivo necesario para lograr lo anterior.

Uso básico:

import Form from 'next/form'

export default function Page() {
  return (
    <Form action="/search">
      {/* Al enviar, el valor del input se añadirá a
          la URL, ej. /search?query=abc */}
      <input name="query" />
      <button type="submit">Submit</button>
    </Form>
  )
}

Referencia

El comportamiento del componente <Form> depende de si la propiedad action recibe un string o una function.

  • Cuando action es un string, el <Form> se comporta como un formulario HTML nativo que usa el método GET. Los datos del formulario se codifican en la URL como parámetros de búsqueda, y cuando se envía el formulario, navega a la URL especificada. Además, Next.js:
    • Precarga (Prefetches) la ruta cuando el formulario se hace visible, esto precarga la interfaz compartida (ej. layout.js y loading.js), resultando en una navegación más rápida.
    • Realiza una navegación del lado del cliente (client-side navigation) en lugar de una recarga completa de página cuando se envía el formulario. Esto conserva la interfaz compartida y el estado del lado del cliente.
  • Cuando action es una función (Server Action), <Form> se comporta como un formulario React, ejecutando la acción cuando se envía el formulario.

Propiedades action (string)

Cuando action es un string, el componente <Form> soporta las siguientes propiedades:

PropiedadEjemploTipoRequerido
actionaction="/search"string (URL o ruta relativa)
replacereplace={false}boolean-
scrollscroll={true}boolean-
prefetchprefetch={true}boolean-
  • action: La URL o ruta a la que navegar cuando se envía el formulario.
    • Un string vacío "" navegará a la misma ruta con los parámetros de búsqueda actualizados.
  • replace: Reemplaza el estado actual del historial en lugar de añadir uno nuevo a la pila del historial del navegador. Por defecto es false.
  • scroll: Controla el comportamiento de desplazamiento durante la navegación. Por defecto es true, lo que significa que se desplazará al inicio de la nueva ruta y mantendrá la posición de desplazamiento para navegación hacia atrás y adelante.
  • prefetch: Controla si la ruta debe ser precargada cuando el formulario se hace visible en el viewport del usuario. Por defecto es true.

Propiedades action (función)

Cuando action es una función, el componente <Form> soporta la siguiente propiedad:

PropiedadEjemploTipoRequerido
actionaction={myAction}function (Server Action)
  • action: La Server Action que se llamará cuando se envíe el formulario. Consulte la documentación de React para más información.

Nota importante: Cuando action es una función, las propiedades replace y scroll se ignoran.

Consideraciones

  • formAction: Puede usarse en campos <button> o <input type="submit"> para sobrescribir la propiedad action. Next.js realizará una navegación del lado del cliente, sin embargo, este enfoque no soporta precarga.
    • Al usar basePath, también debe incluirse en la ruta de formAction. Ej. formAction="/base-path/search".
  • key: No se soporta pasar una propiedad key a un action de tipo string. Si desea activar un re-renderizado o realizar una mutación, considere usar un action de tipo función en su lugar.
  • onSubmit: Puede usarse para manejar la lógica de envío del formulario. Sin embargo, llamar a event.preventDefault() sobrescribirá el comportamiento de <Form> como navegar a la URL especificada.
  • method, encType, target: No están soportados ya que sobrescriben el comportamiento de <Form>.
    • De manera similar, formMethod, formEncType y formTarget pueden usarse para sobrescribir las propiedades method, encType y target respectivamente, y usarlos hará que se recurra al comportamiento nativo del navegador.
    • Si necesita usar estas propiedades, utilice el elemento HTML <form> en su lugar.
  • <input type="file">: Usar este tipo de input cuando action es un string coincidirá con el comportamiento del navegador al enviar el nombre del archivo en lugar del objeto del archivo.

Ejemplos

Formulario de búsqueda que lleva a una página de resultados

Puede crear un formulario de búsqueda que navegue a una página de resultados pasando la ruta como action:

import Form from 'next/form'

export default function Page() {
  return (
    <Form action="/search">
      <input name="query" />
      <button type="submit">Submit</button>
    </Form>
  )
}

Cuando el usuario actualiza el campo de búsqueda y envía el formulario, los datos del formulario se codificarán en la URL como parámetros de búsqueda, ej. /search?query=abc.

Nota importante: Si pasa un string vacío "" a action, el formulario navegará a la misma ruta con los parámetros de búsqueda actualizados.

En la página de resultados, puede acceder a la consulta usando la propiedad searchParams de page.js y usarla para obtener datos de una fuente externa.

import { getSearchResults } from '@/lib/search'

export default async function SearchPage({
  searchParams,
}: {
  searchParams: Promise<{ [key: string]: string | string[] | undefined }>
}) {
  const results = await getSearchResults((await searchParams).query)

  return <div>...</div>
}

Cuando el <Form> se hace visible en el viewport del usuario, la interfaz compartida (como layout.js y loading.js) en la página /search se precargará. Al enviar, el formulario navegará inmediatamente a la nueva ruta y mostrará la interfaz de carga mientras se obtienen los resultados. Puede diseñar la interfaz de respaldo usando loading.js:

export default function Loading() {
  return <div>Loading...</div>
}

Para cubrir casos cuando la interfaz compartida aún no se ha cargado, puede mostrar retroalimentación instantánea al usuario usando useFormStatus.

Primero, cree un componente que muestre un estado de carga cuando el formulario está pendiente:

'use client'
import { useFormStatus } from 'react-dom'

export default function SearchButton() {
  const status = useFormStatus()
  return (
    <button type="submit">{status.pending ? 'Buscando...' : 'Buscar'}</button>
  )
}

Luego, actualice la página del formulario de búsqueda para usar el componente SearchButton:

import Form from 'next/form'
import { SearchButton } from '@/ui/search-button'

export default function Page() {
  return (
    <Form action="/search">
      <input name="query" />
      <SearchButton />
    </Form>
  )
}

Mutaciones con Server Actions

Puede realizar mutaciones pasando una función a la propiedad action.

import Form from 'next/form'
import { createPost } from '@/posts/actions'

export default function Page() {
  return (
    <Form action={createPost}>
      <input name="title" />
      {/* ... */}
      <button type="submit">Crear Post</button>
    </Form>
  )
}

Después de una mutación, es común redirigir al nuevo recurso. Puede usar la función redirect de next/navigation para navegar a la página del nuevo post.

Nota importante: Dado que el "destino" del envío del formulario no se conoce hasta que se ejecuta la acción, <Form> no puede precargar automáticamente la interfaz compartida.

'use server'
import { redirect } from 'next/navigation'

export async function createPost(formData: FormData) {
  // Crear un nuevo post
  // ...

  // Redirigir al nuevo post
  redirect(`/posts/${data.id}`)
}

Luego, en la nueva página, puede obtener datos usando la propiedad params:

import { getPost } from '@/posts/data'

export default async function PostPage({
  params,
}: {
  params: Promise<{ id: string }>
}) {
  const { id } = await params
  const data = await getPost(id)

  return (
    <div>
      <h1>{data.title}</h1>
      {/* ... */}
    </div>
  )
}

Consulte la documentación de Server Actions para más ejemplos.

On this page