Curso react nivel medio

Introducción
useFormStatus es un hook introducido como parte de las nuevas características de React para manejar formularios, diseñado para trabajar con la API de <Form /> en aplicaciones React Server Components (RSC). Este hook permite rastrear el estado de los formularios y manejar estados como "enviando" (submitting) o "enviado" (submitted).


¿Qué es useFormStatus?

useFormStatus te proporciona información sobre el estado actual del formulario:

  • isSubmitting: Indica si el formulario se está enviando.
  • isValid: Indica si el formulario es válido.

Este hook es útil para:

  1. Mostrar indicadores de carga (spinners) durante el envío del formulario.
  2. Deshabilitar elementos del formulario mientras se procesa.
  3. Mostrar mensajes de éxito o error después de enviar.

Requisitos Previos

  1. React Server Components (RSC): useFormStatus está diseñado para trabajar con formularios manejados por el servidor.
  2. Renderizado en Servidor: Generalmente usado en frameworks como Next.js con soporte para React Server Components.

Ejemplo Básico

Código

1import React from "react";
2import { experimental_useFormStatus as useFormStatus } from "react";
3
4function Formulario() {
5  const { isSubmitting } = useFormStatus();
6
7  return (
8    <form action="/api/submit" method="post">
9      <div>
10        <label>
11          Nombre:
12          <input type="text" name="nombre" />
13        </label>
14      </div>
15      <div>
16        <label>
17          Correo:
18          <input type="email" name="correo" />
19        </label>
20      </div>
21      <button type="submit" disabled={isSubmitting}>
22        {isSubmitting ? "Enviando..." : "Enviar"}
23      </button>
24    </form>
25  );
26}
27
28export default Formulario;

Explicación

  1. useFormStatus:
    • Obtiene el estado de envío del formulario (isSubmitting).
  2. Botón Deshabilitado:
    • Mientras el formulario se está enviando, el botón se deshabilita y muestra "Enviando...".

Caso Práctico: Indicador de Carga

Código

1import React from "react";
2import { experimental_useFormStatus as useFormStatus } from "react";
3
4function FormularioConSpinner() {
5  const { isSubmitting } = useFormStatus();
6
7  return (
8    <form action="/api/submit" method="post">
9      <div>
10        <label>
11          Nombre:
12          <input type="text" name="nombre" required />
13        </label>
14      </div>
15      <button type="submit">
16        {isSubmitting ? (
17          <>
18            <span className="spinner"></span> Enviando...
19          </>
20        ) : (
21          "Enviar"
22        )}
23      </button>
24    </form>
25  );
26}
27
28export default FormularioConSpinner;

Estilos para el Spinner

1.spinner {
2  display: inline-block;
3  width: 16px;
4  height: 16px;
5  border: 2px solid #f3f3f3;
6  border-top: 2px solid #3498db;
7  border-radius: 50%;
8  animation: spin 1s linear infinite;
9}
10
11@keyframes spin {
12  0% {
13    transform: rotate(0deg);
14  }
15  100% {
16    transform: rotate(360deg);
17  }
18}

Caso Avanzado: Mensaje de Éxito o Error

Puedes mostrar mensajes dinámicos basados en el estado del formulario.

Código

1import React, { useState } from "react";
2import { experimental_useFormStatus as useFormStatus } from "react";
3
4function FormularioConMensajes() {
5  const { isSubmitting } = useFormStatus();
6  const [mensaje, setMensaje] = useState("");
7
8  const manejarEnvio = async (e) => {
9    e.preventDefault();
10    setMensaje("");
11
12    try {
13      const respuesta = await fetch("/api/submit", {
14        method: "POST",
15        body: new FormData(e.target),
16      });
17
18      if (respuesta.ok) {
19        setMensaje("Formulario enviado con éxito.");
20      } else {
21        setMensaje("Error al enviar el formulario.");
22      }
23    } catch (error) {
24      setMensaje("Hubo un problema. Inténtalo de nuevo.");
25    }
26  };
27
28  return (
29    <form onSubmit={manejarEnvio}>
30      <div>
31        <label>
32          Nombre:
33          <input type="text" name="nombre" required />
34        </label>
35      </div>
36      <button type="submit" disabled={isSubmitting}>
37        {isSubmitting ? "Enviando..." : "Enviar"}
38      </button>
39      {mensaje && <p>{mensaje}</p>}
40    </form>
41  );
42}
43
44export default FormularioConMensajes;

Integración con Next.js

En aplicaciones Next.js, useFormStatus puede combinarse con rutas de la API (/api) para manejar formularios.

API en Next.js

1// /pages/api/submit.js
2export default function handler(req, res) {
3  if (req.method === "POST") {
4    const { nombre, correo } = req.body;
5    // Simular éxito o error
6    if (nombre && correo) {
7      res.status(200).json({ message: "Formulario enviado con éxito" });
8    } else {
9      res.status(400).json({ error: "Faltan datos" });
10    }
11  } else {
12    res.setHeader("Allow", ["POST"]);
13    res.status(405).end(`Método ${req.method} no permitido`);
14  }
15}

Limitaciones de useFormStatus

  1. Solo Compatible con React Server Components:

    • Requiere un entorno que soporte React Server Components.
  2. Dependencia del Envío:

    • Solo puede rastrear formularios que usen la API de formularios del servidor.
  3. No Funciona con Todo Tipo de Formularios:

    • No se puede usar para manejar formularios controlados (useState).

Buenas Prácticas

  1. Habilitar Indicadores de Carga:

    • Usa isSubmitting para deshabilitar botones o mostrar spinners.
  2. Mensajes Dinámicos:

    • Proporciona retroalimentación al usuario después del envío.
  3. Validación en el Cliente y Servidor:

    • Combina validaciones del lado del cliente con validaciones en el servidor para una experiencia robusta.

Conclusión

useFormStatus es un hook diseñado para manejar formularios en aplicaciones con React Server Components, ofreciendo una forma eficiente de rastrear estados como envío o errores. Es ideal para aplicaciones que necesitan manejar formularios complejos con integración directa al servidor.