Barrierefreiheit verbessern
Im vorherigen Kapitel haben wir uns angesehen, wie Fehler (einschließlich 404-Fehler) abgefangen und eine Fallback-Lösung für Benutzer angezeigt werden kann. Allerdings fehlt noch ein wichtiger Teil des Puzzles: die Formularvalidierung. Lassen Sie uns untersuchen, wie serverseitige Validierung mit Server Actions implementiert werden kann und wie Formularfehler mit Reacts useActionState
-Hook angezeigt werden können – unter Berücksichtigung der Barrierefreiheit!
Was ist Barrierefreiheit?
Barrierefreiheit (Accessibility) bezieht sich auf die Gestaltung und Implementierung von Webanwendungen, die von allen genutzt werden können, einschließlich Menschen mit Behinderungen. Es ist ein umfangreiches Thema, das viele Bereiche abdeckt, wie Tastaturnavigation, semantisches HTML, Bilder, Farben, Videos usw.
Obwohl wir in diesem Kurs nicht tief in die Barrierefreiheit eintauchen werden, besprechen wir die in Next.js verfügbaren Barrierefreiheitsfunktionen und einige gängige Praktiken, um Ihre Anwendungen zugänglicher zu gestalten.
Wenn Sie mehr über Barrierefreiheit lernen möchten, empfehlen wir den Kurs Learn Accessibility von web.dev.
Verwendung des ESLint-Barrierefreiheits-Plugins in Next.js
Next.js enthält das Plugin eslint-plugin-jsx-a11y
in seiner ESLint-Konfiguration, um Barrierefreiheitsprobleme frühzeitig zu erkennen. Dieses Plugin warnt beispielsweise, wenn Bilder ohne alt
-Text verwendet werden, die aria-*
- und role
-Attribute falsch eingesetzt werden und mehr.
Optional können Sie dies ausprobieren, indem Sie next lint
als Skript in Ihrer package.json
-Datei hinzufügen:
Führen Sie dann pnpm lint
in Ihrem Terminal aus:
Dies führt Sie durch die Installation und Konfiguration von ESLint für Ihr Projekt. Wenn Sie jetzt pnpm lint
ausführen, sollte folgende Ausgabe erscheinen:
Aber was passiert, wenn Sie ein Bild ohne alt
-Text haben? Lassen Sie uns das herausfinden!
Gehen Sie zu /app/ui/invoices/table.tsx
und entfernen Sie das alt
-Attribut vom Bild. Sie können die Suchfunktion Ihres Editors nutzen, um schnell das <Image>
-Element zu finden:
Führen Sie nun erneut pnpm lint
aus, und Sie sollten folgende Warnung sehen:
Obwohl das Hinzufügen und Konfigurieren eines Linters kein verpflichtender Schritt ist, kann es hilfreich sein, um Barrierefreiheitsprobleme im Entwicklungsprozess zu erkennen.
Verbesserung der Formularbarrierefreiheit
Es gibt drei Dinge, die wir bereits tun, um die Barrierefreiheit in unseren Formularen zu verbessern:
- Semantisches HTML: Verwendung semantischer Elemente (
<input>
,<option>
usw.) anstelle von<div>
. Dies ermöglicht es Hilfstechnologien (AT), sich auf die Eingabeelemente zu konzentrieren und dem Benutzer entsprechende Kontextinformationen bereitzustellen, was das Formular leichter navigierbar und verständlich macht. - Beschriftung: Einbindung von
<label>
und demhtmlFor
-Attribut stellt sicher, dass jedes Formularfeld einen beschreibenden Textlabel hat. Dies verbessert die AT-Unterstützung durch Bereitstellung von Kontext und erhöht die Benutzerfreundlichkeit, da Benutzer auf das Label klicken können, um das entsprechende Eingabefeld zu fokussieren. - Fokusumriss: Die Felder sind so gestaltet, dass sie bei Fokus einen Umriss anzeigen. Dies ist entscheidend für die Barrierefreiheit, da es visuell das aktive Element auf der Seite anzeigt und sowohl Tastatur- als auch Screenreader-Nutzern hilft zu verstehen, wo sie sich im Formular befinden. Sie können dies überprüfen, indem Sie
Tab
drücken.
Diese Praktiken legen eine gute Grundlage, um Ihre Formulare für viele Benutzer zugänglicher zu gestalten. Allerdings behandeln sie nicht die Formularvalidierung und Fehler.
Formularvalidierung
Gehen Sie zu http://localhost:3000/dashboard/invoices/create und senden Sie ein leeres Formular ab. Was passiert?
Sie erhalten einen Fehler! Dies liegt daran, dass leere Formularwerte an Ihre Server Action gesendet werden. Sie können dies verhindern, indem Sie Ihr Formular client- oder serverseitig validieren.
Clientseitige Validierung
Es gibt mehrere Möglichkeiten, Formulare clientseitig zu validieren. Die einfachste wäre, sich auf die vom Browser bereitgestellte Formularvalidierung zu verlassen, indem Sie das required
-Attribut zu den <input>
- und <select>
-Elementen in Ihren Formularen hinzufügen. Zum Beispiel:
Senden Sie das Formular erneut ab. Der Browser zeigt eine Warnung an, wenn Sie versuchen, ein Formular mit leeren Werten abzusenden.
Dieser Ansatz ist generell in Ordnung, da einige ATs die Browser-Validierung unterstützen.
Eine Alternative zur clientseitigen Validierung ist die serverseitige Validierung. Sehen wir uns im nächsten Abschnitt an, wie Sie diese implementieren können. Löschen Sie vorerst die required
-Attribute, falls Sie sie hinzugefügt haben.
Server-seitige Validierung
Durch die Validierung von Formularen auf dem Server können Sie:
- Sicherstellen, dass Ihre Daten im erwarteten Format vorliegen, bevor sie an Ihre Datenbank gesendet werden.
- Das Risiko verringern, dass böswillige Nutzer die clientseitige Validierung umgehen.
- Eine einzige Quelle der Wahrheit für das haben, was als gültige Daten betrachtet wird.
Importieren Sie in Ihrer create-form.tsx
-Komponente den useActionState
-Hook aus react
. Da useActionState
ein Hook ist, müssen Sie Ihr Formular mit der "use client"
-Direktive in eine Client-Komponente umwandeln:
Innerhalb Ihrer Form-Komponente nimmt der useActionState
-Hook:
- Zwei Argumente entgegen:
(action, initialState)
. - Gibt zwei Werte zurück:
[state, formAction]
- den Formularzustand und eine Funktion, die beim Absenden des Formulars aufgerufen wird.
Übergeben Sie Ihre createInvoice
-Aktion als Argument an useActionState
und rufen Sie innerhalb des <form action={}>
-Attributs formAction
auf.
Der initialState
kann alles sein, was Sie definieren. In diesem Fall erstellen Sie ein Objekt mit zwei leeren Schlüsseln: message
und errors
, und importieren Sie den State
-Typ aus Ihrer actions.ts
-Datei. State
existiert noch nicht, aber wir werden ihn als Nächstes erstellen:
Das mag zunächst verwirrend erscheinen, wird aber klarer, sobald Sie die Server-Aktion aktualisieren. Lassen Sie uns das jetzt tun.
In Ihrer action.ts
-Datei können Sie Zod zur Validierung der Formulardaten verwenden. Aktualisieren Sie Ihre FormSchema
wie folgt:
customerId
- Zod wirft bereits einen Fehler, wenn das Kundenfeld leer ist, da es einen Typstring
erwartet. Aber fügen wir eine freundliche Nachricht hinzu, falls der Benutzer keinen Kunden auswählt.amount
- Da Sie den Betragstyp vonstring
zunumber
erzwingen, wird standardmäßig Null zurückgegeben, wenn der String leer ist. Lassen Sie uns Zod mitteilen, dass wir immer einen Betrag größer als 0 mit der.gt()
-Funktion wollen.status
- Zod wirft bereits einen Fehler, wenn das Statusfeld leer ist, da es "pending" oder "paid" erwartet. Fügen wir auch hier eine freundliche Nachricht hinzu, falls der Benutzer keinen Status auswählt.
Aktualisieren Sie als Nächstes Ihre createInvoice
-Aktion, um zwei Parameter zu akzeptieren - prevState
und formData
:
formData
- wie zuvor.prevState
- enthält den Zustand, der vomuseActionState
-Hook übergeben wird. Sie werden ihn in diesem Beispiel nicht in der Aktion verwenden, aber er ist eine erforderliche Eigenschaft.
Ändern Sie dann die Zod-parse()
-Funktion in safeParse()
:
safeParse()
gibt ein Objekt zurück, das entweder ein success
- oder ein error
-Feld enthält. Dies hilft, die Validierung eleganter zu handhaben, ohne diese Logik in den try/catch
-Block einfügen zu müssen.
Überprüfen Sie vor dem Senden der Informationen an Ihre Datenbank mit einer Bedingung, ob die Formularfelder korrekt validiert wurden:
Wenn validatedFields
nicht erfolgreich ist, geben wir die Funktion frühzeitig mit den Fehlermeldungen von Zod zurück.
Tipp: Geben Sie
validatedFields
mit console.log aus und senden Sie ein leeres Formular ab, um dessen Struktur zu sehen.
Schließlich, da Sie die Formularvalidierung separat außerhalb Ihres try/catch-Blocks handhaben, können Sie eine spezifische Nachricht für Datenbankfehler zurückgeben. Ihr endgültiger Code sollte so aussehen:
Großartig, jetzt lassen Sie uns die Fehler in Ihrer Form-Komponente anzeigen. In der create-form.tsx
-Komponente können Sie über den Formular-state
auf die Fehler zugreifen.
Fügen Sie einen ternären Operator hinzu, der nach jedem spezifischen Fehler sucht. Zum Beispiel können Sie nach dem Kundenfeld hinzufügen:
Tipp: Sie können
state
in Ihrer Komponente mit console.log ausgeben und überprüfen, ob alles korrekt verbunden ist. Überprüfen Sie die Konsole in den Dev Tools, da Ihr Formular jetzt eine Client-Komponente ist.
Im obigen Code fügen Sie auch die folgenden ARIA-Labels hinzu:
aria-describedby="customer-error"
: Stellt eine Beziehung zwischen demselect
-Element und dem Fehlermeldungscontainer her. Es zeigt an, dass der Container mitid="customer-error"
dasselect
-Element beschreibt. Screenreader lesen diese Beschreibung, wenn der Benutzer mit demselect
-Feld interagiert, um ihn über Fehler zu informieren.id="customer-error"
: Diesesid
-Attribut identifiziert eindeutig das HTML-Element, das die Fehlermeldung für dasselect
-Eingabefeld enthält. Dies ist notwendig, damitaria-describedby
die Beziehung herstellen kann.aria-live="polite"
: Der Screenreader soll den Benutzer höflich informieren, wenn der Fehler innerhalb desdiv
aktualisiert wird. Wenn sich der Inhalt ändert (z.B. wenn ein Benutzer einen Fehler korrigiert), wird der Screenreader diese Änderungen ankündigen, aber nur, wenn der Benutzer untätig ist, um ihn nicht zu unterbrechen.
Übung: ARIA-Labels hinzufügen
Verwenden Sie das obige Beispiel, um Fehler zu Ihren verbleibenden Formularfeldern hinzuzufügen. Sie sollten auch eine Nachricht am Ende des Formulars anzeigen, falls Felder fehlen. Ihre Benutzeroberfläche sollte so aussehen:

Führen Sie pnpm lint
aus, um zu überprüfen, ob Sie die ARIA-Labels korrekt verwenden, sobald Sie bereit sind.
Wenn Sie sich herausfordern möchten, nehmen Sie das in diesem Kapitel erworbene Wissen und fügen Sie die Formularvalidierung zur edit-form.tsx
-Komponente hinzu.
Sie müssen:
useActionState
zu Ihreredit-form.tsx
-Komponente hinzufügen.- Die
updateInvoice
-Aktion bearbeiten, um Validierungsfehler von Zod zu handhaben. - Die Fehler in Ihrer Komponente anzeigen und ARIA-Labels für bessere Barrierefreiheit hinzufügen.
Erweitern Sie den folgenden Codeausschnitt, um die Lösung zu sehen, sobald Sie bereit sind: