Aufbau hochgradig reaktionsfähiger Benutzeroberflächen mit useOptimistic
Olivia Novak
Dev Intern · Leapcell

Einführung: Benutzererfahrung mit sofortigem Feedback verbessern
In der schnelllebigen Welt der Webanwendungen steht die Benutzererfahrung an erster Stelle. Eine nahtlose, reaktionsschnelle Benutzeroberfläche ist kein Luxus mehr, sondern eine grundlegende Erwartung. Einer der häufigsten Reibungspunkte entsteht jedoch bei der Interaktion mit Daten, die eine serverseitige Verarbeitung erfordern – denken Sie an das Liken eines Beitrags, das Hinzufügen eines Artikels zu einem Warenkorb oder das Absenden eines Formulars. Die kurze Verzögerung, während die Benutzeroberfläche auf eine Bestätigung vom Server wartet, kann zu einer gefühlten Trägheit führen und die gesamte Benutzererfahrung beeinträchtigen. Hier glänzt das Konzept der „optimistischen Updates“. Anstatt auf den Server zu warten, aktualisieren wir die Benutzeroberfläche optimistisch sofort und gehen davon aus, dass die Operation erfolgreich sein wird. Wenn sie fehlschlägt, machen wir die Änderung einfach rückgängig. Dieser Ansatz verbessert die Reaktionsfähigkeit und die Benutzerzufriedenheit dramatisch. Der neue useOptimistic-Hook in React bietet eine leistungsstarke und elegante Möglichkeit, solche optimistischen Updates zu implementieren, und in diesem Artikel werden wir uns eingehend damit beschäftigen, wie Sie ihn nutzen können, um Benutzeroberflächen zu erstellen, die sich wirklich sofort anfühlen.
Optimistische Updates und der useOptimistic-Hook verstehen
Bevor wir uns mit der praktischen Implementierung befassen, lassen Sie uns einige Kernkonzepte klären.
Optimistische Updates: Wie bereits erwähnt, ist ein optimistisches Update ein UI-Muster, bei dem die visuelle Auswirkung einer Aktion sofort nach der Benutzerinteraktion angewendet wird, bevor der Server deren Erfolg bestätigt. Dies gibt den Benutzern sofortiges Feedback und lässt die Anwendung schneller und reaktionsschneller erscheinen. Wenn der Server schließlich einen Fehler zurückgibt, wird die Benutzeroberfläche wieder in ihren ursprünglichen Zustand zurückversetzt.
Wartestatus (Pending State): Dies bezieht sich auf den temporären Zustand der Benutzeroberfläche, nachdem ein optimistisches Update angewendet wurde, aber bevor der Server geantwortet hat. Während dieser Zeit spiegelt die Benutzeroberfläche das erwartete Ergebnis der Operation wider.
Rückgängigmachungsmechanismus (Revert Mechanism): Ein entscheidender Teil optimistischer Updates ist die Fähigkeit, die Benutzeroberfläche wieder in ihren ursprünglichen Zustand zurückzuversetzen, wenn die Serveroperation fehlschlägt. Dies gewährleistet die Datenkonsistenz und verhindert irreführende Informationen.
Der useOptimistic-Hook, der in React 18 eingeführt wurde (derzeit eine experimentelle API), wurde speziell entwickelt, um diese optimistischen Updates zu erleichtern. Er ermöglicht es Ihnen, zwei Zustände zu verwalten: den aktuellen tatsächlichen Zustand und den optimistisch aktualisierten Zustand. Wenn Sie eine Optimistische Aktualisierung auslösen, bietet useOptimistic eine Möglichkeit, einen „Pending State“ basierend auf dem aktuellen Zustand und der beabsichtigten Aktion zu berechnen, der dann sofort in Ihrer Benutzeroberfläche widergespiegelt wird. Sobald die Hintergrundoperation abgeschlossen ist, wird der tatsächliche Zustand aktualisiert und useOptimistic löst den Pending State automatisch auf.
Lassen Sie uns dies anhand eines praktischen Beispiels veranschaulichen: Eine einfache Kommentarfunktion, bei der Benutzer einen Kommentar „liken“ können.
import React, { useState, useOptimistic } from 'react'; interface Comment { id: string; text: string; likes: number; likedByUser: boolean; } // Simulieren eines API-Aufrufs const likeCommentApi = async (commentId: string, isLiking: boolean): Promise<Comment> => { return new Promise((resolve, reject) => { setTimeout(() => { if (Math.random() > 0.1) { // 90% Erfolgswahrscheinlichkeit resolve({ id: commentId, text: 'Dies ist ein Beispielkommentar.', likes: isLiking ? 101 : 100, // Simulieren tatsächlicher Likes likedByUser: isLiking, }); } else { reject(new Error('Fehler beim Liken/Entliken des Kommentars.')); } }, 500); // Simulieren von Netzwerklatenz }); }; function CommentSection() { const initialComment: Comment = { id: 'c1', text: 'Dies ist ein Beispielkommentar.', likes: 100, likedByUser: false, }; const [comment, setComment] = useState<Comment>(initialComment); // useOptimistic gibt [optimisticState, setOptimisticState] zurück // optimisticState ist der aktuelle Zustand, möglicherweise mit angewendeten optimistischen Updates. // setOptimisticState wird verwendet, um ein optimistisches Update auszulösen. const [optimisticComment, addOptimisticComment] = useOptimistic( comment, (currentComment, newLikedState: boolean) => { // Diese Funktion bestimmt den Pending State. // currentComment ist der tatsächliche Zustand, newLikedState ist die von addOptimisticComment übergebene Nutzlast. return { ...currentComment, likes: newLikedState ? currentComment.likes + 1 : currentComment.likes - 1, likedByUser: newLikedState, }; } ); const handleLike = async () => { const newLikedState = !comment.likedByUser; // UI sofort optimistisch aktualisieren addOptimisticComment(newLikedState); try { const updatedComment = await likeCommentApi(comment.id, newLikedState); // Sobald der API-Aufruf erfolgreich ist, den tatsächlichen Zustand aktualisieren. // Dies löst automatisch den optimistischen Zustand auf. setComment(updatedComment); } catch (error) { console.error('API-Fehler:', error); // Wenn der API-Aufruf fehlschlägt, wird die Benutzeroberfläche automatisch zurückgesetzt, // da wir setComment nicht mit dem Fehler aufgerufen haben. // Für komplexere Rücksetzungen oder spezifische Fehlermeldungen // benötigen Sie möglicherweise ein ausgefeilteres Fehlerstatusmanagement. alert('Statusänderung des Likes fehlgeschlagen. Bitte versuchen Sie es erneut.'); // Ein gängiges Muster hier könnte sein, die Benutzeroberfläche ebenfalls // zurückzusetzen, indem der tatsächliche Zustand *zurück* auf den Zustand vor dem optimistischen Update gesetzt wird. // useOptimistic handhabt dies jedoch implizit, wenn setComment nach einem Fehler nicht aufgerufen wird. // Der `optimisticComment` fällt natürlich auf den `comment`-Zustand zurück, wenn `setComment` nicht mit neuen Daten aufgerufen wird. } }; return ( <div style={{ padding: '20px', border: '1px solid #ccc', borderRadius: '8px' }}> <p>{optimisticComment.text}</p> <p>Likes: {optimisticComment.likes}</p> <button onClick={handleLike} disabled={false}> {optimisticComment.likedByUser ? 'Unlike' : 'Like'} </button> {optimisticComment.likedByUser !== comment.likedByUser && ( <span style={{ marginLeft: '10px', color: 'gray' }}> (Aktualisiere...)</span> )} </div> ); } // In Ihrer App.tsx oder ähnlichen Datei: // function App() { // return <CommentSection />; // }
In diesem Beispiel:
- Wir initialisieren unseren 
comment-Zustand mituseState. Dies ist unsere tatsächliche Quelle der Wahrheit. - Danach initialisieren wir 
useOptimisticmit demcomment-Zustand und einer Reducer-Funktion.- Der Reducer 
(currentComment, newLikedState)nimmt den aktuellen tatsächlichen Zustand (currentComment) und die anaddOptimisticCommentübergebene Nutzlast (newLikedState) entgegen. - Er gibt den neuen optimistischen Zustand zurück, der sofort angezeigt wird (
optimisticComment). In unserem Fall erhöhen/verringern wir die Likes und wechselnlikedByUser. 
 - Der Reducer 
 - Wenn 
handleLikeaufgerufen wird, rufen wir zuerstaddOptimisticComment(newLikedState)auf. Dies aktualisiertoptimisticCommentsofort und bewirkt, dass unsere Benutzeroberfläche mit dem "gelikten" Aussehen neu gerendert wird, noch bevor der API-Aufruf beginnt. - Anschließend wird die 
likeCommentApiasynchron aufgerufen. - Wenn der API-Aufruf erfolgreich ist, wird 
setComment(updatedComment)aufgerufen. Dies aktualisiert unseren tatsächlichen Zustand, unduseOptimisticsynchronisiert automatisch und stellt sicher, dassoptimisticCommentnun den erfolgreich aktualisiertencommentwiderspiegelt. - Wenn der API-Aufruf fehlschlägt, wird 
setCommentnicht aufgerufen. Da sich der tatsächlichecomment-Zustand nicht geändert hat, wirdoptimisticCommenteffektiv auf den letzten stabilencomment-Zustand zurückgesetzt und damit die Benutzeroberfläche zurückgesetzt. Wir zeigen dem Benutzer auch eine Benachrichtigung an. 
Dieses Muster lässt unseren like-Button unglaublich schnell erscheinen, da sich die Benutzeroberfläche sofort aktualisiert. Der Benutzer muss nicht auf den Abschluss der Netzwerkanforderung warten, um die Zustandsänderung zu sehen.
Überlegungen und Best Practices
- Fehlerbehandlung: Während 
useOptimisticdie Rücksetzung implizit handhabt, wenn der tatsächliche Zustand nicht aktualisiert wird, erfordern robuste Anwendungen eine explizitere Fehlerbehandlung. Geben Sie dem Benutzer klares Feedback, wenn eine Operation fehlschlägt. - Idempotenz: Optimistische Updates funktionieren am besten mit idempotenten Operationen (Operationen, die mehrmals angewendet werden können, ohne das Ergebnis über die anfängliche Anwendung hinaus zu ändern). Liken/Entliken ist ein gutes Beispiel.
 - Komplexe Formulare: Bei komplexeren Formularen mit mehreren Feldern können Sie die gesamte ausstehende Formulardatenstruktur an 
addOptimisticCommentübergeben oder einen ausgefeilteren Reducer verwenden. - Ladeanzeigen: Selbst bei optimistischen Updates ist es eine gute Praxis, dezent anzuzeigen, dass eine Hintergrundoperation ausgeführt wird (z. B. ein leicht ausgegrauter Ladekreis oder ein Text wie „Aktualisiere...“, wie im Beispiel gezeigt). Dies verwaltet die Erwartungen des Benutzers, insbesondere wenn die Operation länger als üblich dauert oder fehlschlägt.
 - Serverseitige Neuauswertung (Server-Side Revalidation): Nach einer erfolgreichen optimistischen Aktualisierung sollten Sie in Erwägung ziehen, relevante Daten vom Server neu auszuwerten oder sicherzustellen, dass Ihre lokale Zustandsverwaltung (wie zwischengespeicherte Daten) korrekt aktualisiert ist, um Probleme mit veralteten Daten zu vermeiden.
 
Der useOptimistic-Hook vereinfacht die traditionell komplexe Aufgabe der Verwaltung optimistischer UI-Updates und abstrahiert einen Großteil des Boilerplate-Codes für das Zustandsmanagement. Dies ermöglicht es Entwicklern, sich auf die Bereitstellung einer flüssigen und ansprechenden Benutzererfahrung zu konzentrieren.
Fazit: Ein Sprung zu hyper-reaktionsfähigen Benutzeroberflächen
Der useOptimistic-Hook stellt einen bedeutenden Schritt vorwärts beim Aufbau hochgradig reaktionsfähiger React-Anwendungen dar. Indem er Entwicklern die Implementierung optimistischer UI-Updates mit relativer Leichtigkeit ermöglicht, verändert er die Wahrnehmung von Geschwindigkeit und Reaktionsfähigkeit bei den Benutzern grundlegend. Die Übernahme optimistischer Updates, insbesondere mit dem strukturierten Ansatz von useOptimistic, ist entscheidend für die Erstellung moderner Web-Erlebnisse, die sich sofort, angenehm anfühlen und den Benutzer wirklich in den Mittelpunkt stellen. Dieser Hook ermöglicht es uns, die Lücke zwischen Benutzeraktion und Serverbestätigung zu schließen, was zu einem deutlich reibungsloseren und ansprechenderen Interaktionsfluss führt.

