La bibliothèque Formspree React
Installation
Cette bibliothèque suppose que React est déjà installé dans votre environnement en tant que dépendance pair. Nos utilitaires reposent sur les React Hooks, vous devez donc être sur la version 16.8.0 ou supérieure.
npm install @formspree/react
Code source sur GitHub | Package npm
Vous pouvez utiliser cette bibliothèque avec ou sans la CLI Formspree. Cet article suppose que vous créez des formulaires depuis le tableau de bord. Pour obtenir de l’aide sur les projets CLI, consultez notre article sur l’utilisation de la CLI Formspree.
Utilisation
Le hook React useForm est le moyen le plus simple de configurer un formulaire React avec Formspree. Il suffit d’importer @formspree/react puis d’appeler useForm avec le hashid du formulaire, obtenu en créant un formulaire dans le tableau de bord 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>
)
}
Objet d’état
La première valeur du tableau retourné par ce hook est un objet d’état :
const [state, handleSubmit, reset] = useForm('{your-form-id}');
L’objet d’état contient les propriétés suivantes :
| Clé | Description |
|---|---|
submitting | Un booléen indiquant si le formulaire est en cours de soumission (par défaut false) |
succeeded | Un booléen indiquant si le formulaire a été soumis avec succès (par défaut false) |
errors | Une instance de la classe SubmissionError contenant les erreurs de validation côté serveur (par défaut null) |
result | Un objet avec une propriété next qui est l’URL de redirection lorsque la soumission réussit (par défaut null) |
L’état évolue dans le temps de la façon suivante :
- Lorsque
handleSubmitest appelé,submittingdevienttrue - Si la soumission échoue aux validations côté serveur, une nouvelle instance de
errorsest créée avec les erreurs spécifiques - Si la soumission réussit,
succeededdevienttrueetresultn’est plusnull - Une fois la requête de soumission terminée,
submittingredevient toujoursfalse
L’objet errors dispose des méthodes suivantes :
| Clé | Description |
|---|---|
getFormErrors() | Retourne un tableau d’erreurs au niveau du formulaire |
getFieldErrors(field) | Retourne un tableau d’erreurs pour le champ field |
getAllFieldErrors() | Retourne un tableau de paires clé-valeur des erreurs de chaque champ ([field, errors][]) |
Les éléments d’erreur dans l’objet errors possèdent les propriétés suivantes :
| Clé | Description |
|---|---|
message | Un fragment de message d’erreur lisible par l’humain (ex. : “is required”) |
code | Un code d’erreur adapté aux machines (voir les codes d’erreur ci-dessous) |
details | Un objet contenant diverses propriétés supplémentaires sur l’erreur. Par exemple, lors de l’utilisation avec Stripe, il contiendra un champ stripeCode avec l’erreur exacte retournée par Stripe |
Réinitialisation
La troisième valeur du tableau retourné par le hook est une fonction de réinitialisation.
const [state, handleSubmit, reset] = useForm('{your-form-id}');
Cette fonction permet de réinitialiser l’objet d’état après qu’une requête de soumission de formulaire a été complétée. Elle efface les propriétés result et errors, et remet les propriétés booléennes submitting et succeeded à leur état par défaut (c’est-à-dire false). Vous pouvez utiliser cette méthode sur la page de remerciement affichée après la soumission pour permettre à l’utilisateur de réinitialiser le formulaire et de le soumettre à nouveau.
Voici un exemple montrant comment utiliser la fonction reset() dans un formulaire :
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>
);
}
Erreurs de validation
Voici un exemple de formulaire utilisant le composant ValidationError pour afficher les erreurs de champ :
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>
)
}
Le composant ValidationError accepte les propriétés spéciales suivantes :
field— le nom du champ pour lequel afficher les erreurs. Si aucun attributfieldn’est fourni, les erreurs générales (non liées à un champ) seront affichées. (Voir les codes d’erreur ci-dessous)errors— l’objet contenant les erreurs de validation (requis)prefix— le nom convivial du champ (optionnel, par défaut “This field”)
Toutes les autres propriétés (comme className) sont transmises au wrapper <div>. Si le champ est invalide, ce composant affiche un <div> contenant le message d’erreur :
<div {...props}>
{prefix} {message}
</div>
Options supplémentaires
Ce hook accepte deux arguments : la clé du formulaire et un objet contenant des options.
const [state, handleSubmit, reset] = useForm('{your-form-key}', options);
Les options acceptées sont les suivantes :
| Clé | Type | Description |
|---|---|---|
data | object | Un objet contenant des chaînes ou des fonctions à fusionner avec les données de votre formulaire |
client | Formspree | Une instance du client Formspree |
Exemple d’utilisation
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;
}
}
});
Utilisation avec Stripe
La bibliothèque Formspree React inclut la prise en charge des paiements via Stripe. Elle gère la majeure partie de la gestion d’état côté front-end nécessaire pour créer des paiements et effectuer l’authentification forte du client (SCA). Le backend Formspree se charge ensuite de soumettre les paiements à Stripe. Ensemble, ils réduisent considérablement l’effort de développement nécessaire pour créer un formulaire de paiement.
La fonctionnalité Stripe est chargée à la demande. Cela signifie que seul un wrapper Stripe minimal (seulement 6 ko compressé) est inclus dans le bundle de @formspree/react. Le reste de la bibliothèque Stripe n’est chargé que si et quand les éléments Stripe sont rendus pour la première fois.
Pour utiliser Stripe, enveloppez d’abord votre application avec le composant FormspreeProvider en incluant la prop stripePK avec votre clé publique Stripe.
import { FormspreeProvider } from '@formspree/react';
function MyApp() {
return (
<FormspreeProvider
stripePK={'{your-stripe-publishable-key}'}
>
<PaymentForm />
</FormspreeProvider>
)
}
Ensuite, lors de la construction de votre formulaire, utilisez le composant CardElement exporté par @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>
)
}
Le composant CardElement est transmis directement depuis @stripe/react-stripe-js. Il est exporté par Formspree React uniquement pour garantir la cohérence des versions. La documentation du composant CardElement est disponible ici.
Notez le nom de champ “paymentMethod” sur ValidationError. C’est le nom de champ utilisé pour transmettre les données de Stripe à Formspree, et il doit être passé à ValidationError pour intercepter les erreurs Stripe pertinentes.
Utilisation avec une bibliothèque de formulaires externe
Le hook React useSubmit est un moyen simple d’intégrer une autre bibliothèque de formulaires avec Formspree. Il suffit d’importer @formspree/react puis d’appeler useSubmit avec le hashid du formulaire, obtenu en créant un formulaire dans le tableau de bord 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>
);
}
Codes d’erreur
Les codes d’erreur suivants peuvent apparaître dans le tableau d’erreurs de l’objet d’état :
| Code | Erreur de champ | Description |
|---|---|---|
INACTIVE | Le formulaire a été désactivé | |
BLOCKED | Le formulaire a été bloqué | |
EMPTY | Aucune donnée n’a été soumise | |
PROJECT_NOT_FOUND | Une clé de projet invalide a été utilisée pour soumettre le formulaire | |
FORM_NOT_FOUND | Un hashid de formulaire invalide a été utilisé pour soumettre le formulaire | |
NO_FILE_UPLOADS | Les téléversements de fichiers ne sont pas pris en charge pour ce formulaire | |
TOO_MANY_FILES | Le formulaire a été soumis avec trop de fichiers joints | |
FILES_TOO_BIG | Un ou plusieurs fichiers téléversés dépassent la taille maximale autorisée | |
REQUIRED_FIELD_MISSING | ✓ | Un champ est obligatoire mais aucune valeur n’a été fournie |
REQUIRED_FIELD_EMPTY | ✓ | Un champ est obligatoire mais une chaîne vide ou nulle a été fournie |
TYPE_EMAIL | ✓ | Un champ doit contenir une adresse e-mail |
TYPE_NUMERIC | ✓ | Un champ doit contenir un nombre |
TYPE_TEXT | ✓ | Un champ doit contenir du texte |
STRIPE_CLIENT_ERROR | ✓ | Clé Stripe manquante |
STRIPE_SCA_ERROR | ✓ | Erreur SCA Stripe. Voir details |