La librería Formspree React
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:
| Clave | Descripción |
|---|---|
submitting | Un booleano que indica si el formulario se está enviando actualmente (por defecto false) |
succeeded | Un booleano que indica si el formulario se envió correctamente (por defecto false) |
errors | Una instancia de la clase SubmissionError que contiene los errores de validación del lado del servidor (por defecto null) |
result | Un 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,submittingse vuelvetrue - Si el envío falla en las validaciones del lado del servidor, se crea una nueva instancia de
errorscon los errores específicos - Si el envío tiene éxito,
succeededse vuelvetrueyresultno esnull - Después de que la solicitud de envío finaliza,
submittingsiempre se vuelvefalse
El objeto errors tiene los siguientes métodos:
| Clave | Descripció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:
| Clave | Descripción |
|---|---|
message | Un fragmento de mensaje de error legible para humanos (por ejemplo, “is required”) |
code | Un código de error orientado a máquina (consulta los códigos de error abajo) |
details | Un 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 atributofield, 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:
| Clave | Tipo | Descripción |
|---|---|---|
data | object | Un objeto que contiene strings o funciones para fusionar con los datos de tu formulario |
client | Formspree | Una 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ódigo | Error de campo | Descripción |
|---|---|---|
INACTIVE | El formulario ha sido deshabilitado | |
BLOCKED | El formulario ha sido bloqueado | |
EMPTY | No se enviaron datos | |
PROJECT_NOT_FOUND | Se utilizó una clave de proyecto inválida para enviar el formulario | |
FORM_NOT_FOUND | Se utilizó un hashid de formulario inválido para enviar el formulario | |
NO_FILE_UPLOADS | No se admiten cargas de archivos para este formulario | |
TOO_MANY_FILES | El formulario se envió con demasiados archivos adjuntos | |
FILES_TOO_BIG | Uno o más archivos cargados excedieron el tamaño máximo permitido | |
REQUIRED_FIELD_MISSING | ✓ | Un campo es obligatorio, pero no se proporcionó ningún valor |
REQUIRED_FIELD_EMPTY | ✓ | Un campo es obligatorio, pero se proporcionó una cadena en blanco o vacía |
TYPE_EMAIL | ✓ | Un campo debe contener un correo electrónico |
TYPE_NUMERIC | ✓ | Un campo debe contener un número |
TYPE_TEXT | ✓ | Un campo debe contener texto |
STRIPE_CLIENT_ERROR | ✓ | Falta la clave de Stripe |
STRIPE_SCA_ERROR | ✓ | Error de SCA de Stripe. Consulta details |