⌘I

La librería Formspree React

Updated January 8, 2026 ·
llmstxt
Also available in:

Instalación

Esta librería asume que React ya está instalado en tu entorno como una dependencia peer. Nuestros helpers dependen de React Hooks, por lo que debes estar en la versión 16.8.0 o superior.

npm install @formspree/react

Código fuente en GitHub | Paquete npm

Puedes usar esta librería con o sin la Formspree CLI. Este artículo asume que estás creando formularios en el panel de control. Para obtener ayuda con proyectos de CLI, consulta nuestro artículo sobre cómo usar la Formspree CLI.

Uso

El hook de React useForm React hook es la forma más sencilla de configurar un formulario de React con Formspree. Solo importa @formspree/react y luego llama a useForm con el hashid del formulario obtenido al crear un formulario en el panel de Formspree.

import { useForm } from '@formspree/react';

function MyForm() {
  const [state, handleSubmit, reset] = useForm('{your-form-id}');
  if (state.succeeded) {
    return <div>Thank you for signing up!</div>;
  }
  return (
    <form onSubmit={handleSubmit}>
      <label htmlFor="email">Email</label>
      <input id="email" type="email" name="email" />
      <button type="submit" disabled={state.submitting}>Sign up</button>
    </form>
  )
}

Objeto de estado

El primer valor del array devuelto por este hook es un objeto de estado:

const [state, handleSubmit, reset] = useForm('{your-form-id}');

El objeto de estado contiene las siguientes propiedades:

ClaveDescripción
submittingUn booleano que indica si el formulario se está enviando actualmente (por defecto false)
succeededUn booleano que indica si el formulario se envió correctamente (por defecto false)
errorsUna instancia de la clase SubmissionError que contiene los errores de validación del lado del servidor (por defecto null)
resultUn objeto con una propiedad next que es la URL de redirección cuando el envío es exitoso (por defecto null)

El estado cambia con el tiempo de las siguientes formas:

  • Cuando se llama a handleSubmit, submitting se vuelve true
  • Si el envío falla en las validaciones del lado del servidor, se crea una nueva instancia de errors con los errores específicos
  • Si el envío tiene éxito, succeeded se vuelve true y result no es null
  • Después de que la solicitud de envío finaliza, submitting siempre se vuelve false

El objeto errors tiene los siguientes métodos:

ClaveDescripción
getFormErrors()Devuelve un array de errores a nivel de formulario
getFieldErrors(field)Devuelve un array de errores para el campo field
getAllFieldErrors()Devuelve un array de pares clave-valor de los errores a nivel de campo de todos los campos ([field, errors][])

Los elementos de error en el objeto errors tienen las siguientes propiedades:

ClaveDescripción
messageUn fragmento de mensaje de error legible para humanos (por ejemplo, “is required”)
codeUn código de error orientado a máquina (consulta los códigos de error abajo)
detailsUn objeto que contiene varias propiedades adicionales sobre el error. Por ejemplo, cuando se usa con Stripe, contendrá un campo stripeCode con el error exacto de Stripe

Reset

El tercer valor del array devuelto por el hook es una función de reset.

const [state, handleSubmit, reset] = useForm('{your-form-id}');

Esta función se utiliza para restablecer el objeto de estado después de que se ha completado una solicitud de envío del formulario. Limpia las propiedades result y errors, y establece las propiedades booleanas submitting y succeeded a su estado por defecto (es decir, false). Puedes usar este método en la página de “agradecimiento” que muestras después de que se ha completado la solicitud de envío del formulario para permitir al usuario restablecer el formulario y enviarlo nuevamente.

A continuación se muestra un ejemplo de cómo usar la función reset() en un formulario:

function TestForm() {
    const [state, submit, reset] = useForm('{your-form-id}');

    if (state.submitting) {
        return <p>Submitting…</p>;
    }

    if (state.succeeded) {
        return (
            <div>
                <p>Thanks!</p>;<button onClick={reset}>Reset</button>
            </div>
        );
    }

    return (
        <div>
            <h1>Form</h1>
            <form onSubmit={submit}>
                <label htmlFor="email">Email</label>
                <input
                    id="email"
                    type="email"
                    name="email"
                    defaultValue="test@example.com"
                />

                <button type="submit">Sign up</button>

            </form>
        </div>
    );
}

Errores de validación

A continuación se muestra un ejemplo de un formulario que utiliza el componente ValidationError para mostrar errores de campo:

import { ValidationError, useForm } from '@formspree/react';

function MyForm() {
  const [state, handleSubmit] = useForm('{your-form-id}');
  if (state.succeeded) {
    return <div>Thank you for signing up!</div>;
  }
  return (
    <form onSubmit={handleSubmit}>
      <label htmlFor="email">Email</label>
      <input id="email" type="email" name="email" required />
      <ValidationError field="email" prefix="Email" errors={state.errors} />
      <button type="submit" disabled={state.submitting}>Sign up</button>
    </form>
  )
}

El componente ValidationError acepta las siguientes propiedades especiales:

  • field — el nombre del campo para el cual se mostrarán los errores. Si no se proporciona el atributo field, se reportarán los errores generales (no de campo). (Consulta los códigos de error abajo)
  • errors — el objeto que contiene los errores de validación (obligatorio)
  • prefix — el nombre amigable del campo (opcional, por defecto “This field”)

Todas las demás props (como className) se pasan al wrapper <div>. Si el campo dado es inválido, este componente renderiza un <div> que contiene el mensaje de error:

<div {...props}>
  {prefix} {message}
</div>

Opciones adicionales

Este hook acepta dos argumentos: la clave del formulario y un objeto que contiene opciones.

const [state, handleSubmit, reset] = useForm('{your-form-key}', options);

Estas son las opciones aceptables:

ClaveTipoDescripción
dataobjectUn objeto que contiene strings o funciones para fusionar con los datos de tu formulario
clientFormspreeUna instancia del cliente de Formspree

Ejemplo de uso

const [state, handleSubmit, reset] = useForm('{your-form-id}', {
  data: {
    subject: 'Someone joined the newsletter',
    pageTitle: function() {
      // This function will be evaluated at submission time
      return document.title;
    }
  }
});

Uso con Stripe

La librería Formspree React incluye soporte para pagos a través de Stripe. La librería se encarga de la mayor parte de la gestión del estado de front end necesaria para crear pagos y realizar la Strong Customer Authentication (SCA). El backend de Formspree se encarga luego de enviar los pagos a Stripe. En conjunto, Formspree reduce drásticamente el esfuerzo de desarrollo necesario para crear un formulario de pago.

La funcionalidad de Stripe se carga de forma diferida (lazy loading). Esto significa que solo se incluye un wrapper mínimo de Stripe (apenas 6k comprimidos) con @formspree/react. La mayor parte de la librería de Stripe se carga solo si, y cuando, los elementos de Stripe se renderizan por primera vez.

Para usar Stripe, primero envuelve tu aplicación con el componente FormspreeProvider e incluye la prop stripePK con tu clave publicable de Stripe.

import { FormspreeProvider } from '@formspree/react';

function MyApp() {
  return (
    <FormspreeProvider
      stripePK={'{your-stripe-publishable-key}'}
    >
      <PaymentForm />
    </FormspreeProvider>
  )
}

Luego, al construir tu formulario, usa el componente CardElement exportado por @formspree/react.

import { useForm, CardElement, ValidationError } from '@formspree/react';

function PaymentForm() {
  const [state, handleSubmit] = useForm('{your-form-id}');

  if (state.succeeded) {
    return <div>Payment has been handled successfully!</div>;
  }

  return (
    <form onSubmit={handleSubmit}>
      <div>
        <label htmlFor="email">Email</label>
        <input id="email" type="email" name="email" />
      </div>
      <div>
        <label>Card details</label>
        <CardElement />
        <ValidationError
          field="paymentMethod"
          errors={state.errors}
        />
      </div>
      <button type="submit" disabled={state.submitting}>
        {state.submitting ? 'Handling payment...' : 'Pay'}
      </button>
    </form>
  )
}

El componente CardElement se pasa directamente desde @stripe/react-stripe-js. Es exportado por Formspree React solo para garantizar la consistencia de versiones. La documentación del componente CardElement se encuentra aquí.

Observa el nombre de campo “paymentMethod” en ValidationError. Este es el nombre de campo utilizado para enviar datos desde Stripe a Formspree, y debe pasarse a ValidationError para capturar los errores relevantes de Stripe.

Uso con una librería de formularios externa

El hook de React useSubmit React hook es una manera fácil de integrar otra librería de formularios con Formspree. Solo importa @formspree/react y luego llama a useSubmit con el hashid del formulario obtenido al crear un formulario en el panel de Formspree.

import { useSubmit } from '@formspree/react';
import { useForm } from 'react-hook-form';

type Inputs = {
  email: string;
  message: string;
  name: string;
};

export function WithReactHookForm() {
  const {
    formState: { errors, isSubmitSuccessful, isSubmitting },
    handleSubmit,
    register,
    setError,
  } = useForm<Inputs>();

  const submit = useSubmit<Inputs>(
    process.env.REACT_APP_REACT_HOOK_FORM_ID as string,
    {
      onError(errs) {
        const formErrs = errs.getFormErrors();
        for (const { code, message } of formErrs) {
          setError(`root.${code}`, {
            type: code,
            message,
          });
        }

        const fieldErrs = errs.getAllFieldErrors();
        for (const [field, errs] of fieldErrs) {
          setError(field, {
            message: errs.map((e) => e.message).join(', '),
          });
        }
      },
    }
  );

  return (
    <div>
      {isSubmitSuccessful ? (
        <h2>Your message has been sent successfully!</h2>
      ) : (
        <form onSubmit={handleSubmit(submit)}>
          <div className="block">
            <label htmlFor="email">Email</label>
            <input {...register('email')} id="email" type="email" />
            {errors.email && <p className="error">{errors.email.message}</p>}
          </div>
          <div className="block">
            <label htmlFor="name">Name</label>
            <input {...register('name')} id="name" />
            {errors.name && <p className="error">{errors.name.message}</p>}
          </div>
          <div className="block">
            <label htmlFor="message">Message</label>
            <textarea {...register('message')} id="message" rows={10} />
          </div>
          {errors.root && (
            <div className="block">
              <ul className="error">
                {Object.values(errors.root).map((err) => {
                  if (typeof err !== 'object') {
                    return <li key={err}>{err}</li>;
                  }
                  const { type, message } = err;
                  return <li key={type}>{message}</li>;
                })}
              </ul>
            </div>
          )}
          <button type="submit" disabled={isSubmitting}>
            {isSubmitting ? 'Submitting...' : 'Submit'}
          </button>
        </form>
      )}
    </div>
  );
}

Códigos de error

Los siguientes códigos de error pueden aparecer en el array de errores del objeto de estado:

CódigoError de campoDescripción
INACTIVEEl formulario ha sido deshabilitado
BLOCKEDEl formulario ha sido bloqueado
EMPTYNo se enviaron datos
PROJECT_NOT_FOUNDSe utilizó una clave de proyecto inválida para enviar el formulario
FORM_NOT_FOUNDSe utilizó un hashid de formulario inválido para enviar el formulario
NO_FILE_UPLOADSNo se admiten cargas de archivos para este formulario
TOO_MANY_FILESEl formulario se envió con demasiados archivos adjuntos
FILES_TOO_BIGUno o más archivos cargados excedieron el tamaño máximo permitido
REQUIRED_FIELD_MISSINGUn campo es obligatorio, pero no se proporcionó ningún valor
REQUIRED_FIELD_EMPTYUn campo es obligatorio, pero se proporcionó una cadena en blanco o vacía
TYPE_EMAILUn campo debe contener un correo electrónico
TYPE_NUMERICUn campo debe contener un número
TYPE_TEXTUn campo debe contener texto
STRIPE_CLIENT_ERRORFalta la clave de Stripe
STRIPE_SCA_ERRORError de SCA de Stripe. Consulta details