Die Formspree React-Bibliothek
Installation
Diese Bibliothek setzt voraus, dass React bereits als Peer-Dependency in deiner Umgebung installiert ist. Unsere Helfer basieren auf React Hooks, daher musst du Version 16.8.0 oder höher verwenden.
npm install @formspree/react
Quellcode auf GitHub | npm-Paket
Du kannst diese Bibliothek mit oder ohne das Formspree CLI verwenden. Dieser Artikel geht davon aus, dass du Formulare im Dashboard erstellst. Hilfe zu CLI-Projekten findest du in unserem Artikel zur Verwendung des Formspree CLI.
Verwendung
Der useForm-React-Hook ist der einfachste Weg, ein React-Formular mit Formspree einzurichten. Importiere einfach @formspree/react und rufe dann useForm mit der hashid des Formulars auf, die du durch das Erstellen eines Formulars im Formspree-Dashboard erhältst.
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>
)
}
State-Objekt
Der erste Wert in dem von diesem Hook zurückgegebenen Array ist ein State-Objekt:
const [state, handleSubmit, reset] = useForm('{your-form-id}');
Das State-Objekt enthält die folgenden Eigenschaften:
| Schlüssel | Beschreibung |
|---|---|
submitting | Ein Boolean, der angibt, ob das Formular gerade übermittelt wird (Standardwert false) |
succeeded | Ein Boolean, der angibt, ob das Formular erfolgreich übermittelt wurde (Standardwert false) |
errors | Eine Instanz der Klasse SubmissionError, die serverseitige Validierungsfehler enthält (Standardwert null) |
result | Ein Objekt mit einer Eigenschaft next, die die Weiterleitungs-URL ist, wenn die Übermittlung erfolgreich ist (Standardwert null) |
Der State ändert sich im Laufe der Zeit auf folgende Weise:
- Wenn
handleSubmitaufgerufen wird, wirdsubmittingzutrue - Wenn die Übermittlung die serverseitigen Validierungen nicht besteht, wird eine neue Instanz von
errorsmit den spezifischen Fehlern erstellt - Wenn die Übermittlung erfolgreich ist, wird
succeededzutrueundresultist nichtnull - Nachdem die Übermittlungsanfrage abgeschlossen ist, wird
submittingimmer zufalse
Das errors-Objekt hat die folgenden Methoden:
| Schlüssel | Beschreibung |
|---|---|
getFormErrors() | Gibt ein Array von Fehlern auf Formularebene zurück |
getFieldErrors(field) | Gibt ein Array von Fehlern für das field zurück |
getAllFieldErrors() | Gibt ein Array von Schlüssel-Wert-Paaren mit Fehlern auf Feldebene aller Felder zurück ([field, errors][]) |
Die Fehlerelemente im errors-Objekt haben die folgenden Eigenschaften:
| Schlüssel | Beschreibung |
|---|---|
message | Ein menschenlesbares Fehlermeldungsfragment (z. B. “is required”) |
code | Ein maschinenfreundlicher Fehlercode (siehe Fehlercodes unten) |
details | Ein Objekt mit verschiedenen zusätzlichen Eigenschaften zum Fehler. Bei Verwendung mit Stripe enthält es beispielsweise ein Feld stripeCode, das den genauen Fehler von Stripe enthält |
Reset
Der dritte Wert in dem vom Hook zurückgegebenen Array ist eine Reset-Funktion.
const [state, handleSubmit, reset] = useForm('{your-form-id}');
Diese Funktion wird verwendet, um das State-Objekt zurückzusetzen, nachdem eine Formularübermittlungsanfrage abgeschlossen wurde. Sie leert die Eigenschaften result und errors und setzt die Boolean-Eigenschaften submitting und succeeded auf ihren Standardzustand zurück (d. h. false). Du kannst diese Methode auf der Dankesseite verwenden, die du nach Abschluss der Formularübermittlungsanfrage anzeigst, damit der Benutzer das Formular zurücksetzen und erneut übermitteln kann.
Hier ist ein Beispiel, das zeigt, wie die Funktion reset() in einem Formular verwendet wird:
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>
);
}
Validierungsfehler
Hier ist ein Beispielformular, das die Komponente ValidationError verwendet, um Feldfehler anzuzeigen:
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>
)
}
Die Komponente ValidationError akzeptiert die folgenden speziellen Eigenschaften:
field— der Name des Felds, für das Fehler angezeigt werden sollen. Wenn keinfield-Attribut angegeben wird, werden allgemeine (nicht feldbezogene) Fehler gemeldet. (Siehe Fehlercodes unten)errors— das Objekt, das die Validierungsfehler enthält (erforderlich)prefix— der benutzerfreundliche Name des Felds (optional, Standardwert “This field”)
Alle anderen Props (wie className) werden an den <div>-Wrapper durchgereicht. Wenn das angegebene Feld ungültig ist, rendert diese Komponente ein <div>, das die Fehlermeldung enthält:
<div {...props}>
{prefix} {message}
</div>
Zusätzliche Optionen
Dieser Hook akzeptiert zwei Argumente: den Formularschlüssel und ein Objekt, das Optionen enthält.
const [state, handleSubmit, reset] = useForm('{your-form-key}', options);
Hier sind die zulässigen Optionen:
| Schlüssel | Typ | Beschreibung |
|---|---|---|
data | object | Ein Objekt, das Strings oder Funktionen enthält, die mit deinen Formulardaten zusammengeführt werden |
client | Formspree | Eine Instanz des Formspree-Clients |
Verwendungsbeispiel
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;
}
}
});
Verwendung mit Stripe
Die Formspree React-Bibliothek bietet Unterstützung für Zahlungen über Stripe. Die Bibliothek übernimmt den größten Teil des Frontend-State-Managements, das für das Erstellen von Zahlungen und das Durchführen der Strong Customer Authentication (SCA) erforderlich ist. Das Formspree-Backend kümmert sich dann um die Übermittlung der Zahlungen an Stripe. Zusammen reduziert Formspree den Entwicklungsaufwand für die Erstellung eines Zahlungsformulars erheblich.
Die Stripe-Funktionalität wird per Lazy Loading geladen. Das bedeutet, dass nur ein minimaler Stripe-Wrapper (nur 6k komprimiert) mit @formspree/react gebündelt wird. Der Großteil der Stripe-Bibliothek wird nur geladen, falls und wann Stripe-Elemente zum ersten Mal gerendert werden.
Um Stripe zu verwenden, umschließe zunächst deine App mit der Komponente FormspreeProvider und füge die Prop stripePK mit deinem öffentlichen Stripe-Schlüssel (publishable key) hinzu.
import { FormspreeProvider } from '@formspree/react';
function MyApp() {
return (
<FormspreeProvider
stripePK={'{your-stripe-publishable-key}'}
>
<PaymentForm />
</FormspreeProvider>
)
}
Verwende dann beim Erstellen deines Formulars die von @formspree/react exportierte Komponente CardElement.
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>
)
}
Die Komponente CardElement wird direkt von @stripe/react-stripe-js durchgereicht. Sie wird von Formspree React nur exportiert, um die Versionskonsistenz sicherzustellen. Die Dokumentation für die Komponente CardElement findest du hier.
Beachte den Feldnamen “paymentMethod” bei ValidationError. Dies ist der Feldname, der zum Senden von Daten von Stripe an Formspree verwendet wird, und muss an ValidationError übergeben werden, um relevante Stripe-Fehler abzufangen.
Verwendung mit einer externen Formularbibliothek
Der useSubmit-React-Hook ist eine einfache Möglichkeit, eine andere Formularbibliothek mit Formspree zu integrieren. Importiere einfach @formspree/react und rufe dann useSubmit mit der hashid des Formulars auf, die du durch das Erstellen eines Formulars im Formspree-Dashboard erhältst.
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>
);
}
Fehlercodes
Die folgenden Fehlercodes können im errors-Array des State-Objekts erscheinen:
| Code | Feldfehler | Beschreibung |
|---|---|---|
INACTIVE | Das Formular wurde deaktiviert | |
BLOCKED | Das Formular wurde blockiert | |
EMPTY | Es wurden keine Daten übermittelt | |
PROJECT_NOT_FOUND | Zum Übermitteln des Formulars wurde ein ungültiger Projektschlüssel verwendet | |
FORM_NOT_FOUND | Zum Übermitteln des Formulars wurde eine ungültige Formular-hashid verwendet | |
NO_FILE_UPLOADS | Datei-Uploads werden für dieses Formular nicht unterstützt | |
TOO_MANY_FILES | Das Formular wurde mit zu vielen Dateianhängen übermittelt | |
FILES_TOO_BIG | Eine oder mehrere hochgeladene Dateien überschreiten die maximale Dateigröße | |
REQUIRED_FIELD_MISSING | ✓ | Ein Feld ist erforderlich, aber es wurde kein Wert angegeben |
REQUIRED_FIELD_EMPTY | ✓ | Ein Feld ist erforderlich, aber es wurde eine leere oder leerer String angegeben |
TYPE_EMAIL | ✓ | Ein Feld sollte eine E-Mail enthalten |
TYPE_NUMERIC | ✓ | Ein Feld sollte eine Zahl enthalten |
TYPE_TEXT | ✓ | Ein Feld sollte Text enthalten |
STRIPE_CLIENT_ERROR | ✓ | Stripe-Schlüssel fehlt |
STRIPE_SCA_ERROR | ✓ | Stripe-SCA-Fehler. Siehe details |