useButtonFeedback
Führt eine asynchrone Aktion durch Laden, Erfolg und Fehler, überspringt den Spinner bei schnellen Anfragen und hält einen Fehler, während du ihn liest.
pnpm dlx shadcn@latest add https://hextaui.com/r/use-button-feedback.jsonFügt den Hook und alles, wovon er abhängt, zu deinem Projekt hinzu.
Kopiere den folgenden Code und füge ihn in dein Projekt ein.
hooks/use-button-feedback.ts Passe die Importpfade an dein Projekt-Setup an.
<Button feedback> führt diesen Ablauf für dich aus, wenn sein onClick ein Promise zurückgibt. Nutze den Hook, wenn die Arbeit woanders beginnt, etwa im onSubmit eines Formulars, einem Tastenkürzel oder einem Blur. Er funktioniert auch, wenn der Status zu etwas gehört, das kein Button ist.
track() nimmt ein Promise oder eine Funktion, die eines zurückgibt, und führt status durch idle, loading, dann success oder error und zurück zu idle. Das Timing macht es ruhig.
| Schritt | Beschreibung |
|---|---|
0–150ms | Der Status bleibt idle. Eine Anfrage, die in diesem Fenster endet, geht direkt zu success oder error, ohne Spinner. |
loading | Ab 150ms angezeigt. Einmal angezeigt, hält er mindestens 400ms, sodass er nie aufblitzt. |
success | Standardmäßig 2 Sekunden gehalten, dann zurück zu idle. |
error | Standardmäßig 4 Sekunden gehalten. Solange der Zeiger über dem Button ist oder er Tastaturfokus hat, wartet das Zurücksetzen, bis beides endet, plus 600ms. |
- Aufrufe von
track()während eine Anfrage läuft, werden ignoriert, sodass ein Doppelklick oder eine gehaltene Enter-Taste die Anfrage nie zweimal sendet. - Eine an
track()übergebene Funktion, die synchron wirft, wird wie ein abgelehntes Promise behandelt. reset()geht sofort zu idle zurück. Was die verworfene Anfrage später tut, wird ignoriert, ebenso alles, was nach dem Unmount der Komponente endet.- Das Halten des Fehlers zählt nur echtes Maus-Hovern und Tastaturfokus. Touch hat kein Hover, und der Fokus nach einem Klick ist nicht
:focus-visible, sodass keines von beiden den Fehler festhält.
Formulare
Rufe track() aus onSubmit auf und spreade buttonProps auf den Submit-Button. Entferne das @, um den Fehler zu sehen.
Status ohne Button
Lies status, um beliebige UI zu steuern. Diese Notiz speichert, wenn sie den Fokus verliert, und zeigt das Ergebnis daneben, in einem role="status"-Bereich, den Screenreader ansagen.
resetAfter nimmt eine Zahl für beide Ausgänge oder ein Objekt, um jeden einzeln zu setzen. error hält den letzten Ablehnungsgrund, sodass du ihn im Label zeigen kannst, wie es das Beispiel Fehlerdetails des Button tut.
- Gib jedem Button seinen eigenen Hook. Zwei Buttons, die sich ein
buttonPropsteilen, zeigen beide denselben Status. onStatusChangeundonErrorrufen immer die zuletzt übergebene Funktion auf, daher sind Inline-Funktionen in Ordnung.- Nutze
isPending(), um Arbeit außerhalb vontrack()abzusichern. Es liest eine Ref und ist daher auch vor dem nächsten Render korrekt.
| Prop | Typ | Standard |
|---|---|---|
resetAfterWie lange success und error stehen bleiben, bevor es zu idle zurückgeht. | number | { success?: number; error?: number } | { success: 2000, error: 4000 } |
onStatusChangeWird bei jeder Statusänderung aufgerufen. | (status: ButtonStatus) => void | – |
onErrorWird mit dem Ablehnungsgrund aufgerufen. | (error: unknown) => void | – |
| Property | Beschreibung |
|---|---|
track(action) | Übergib ein Promise oder eine Funktion, die eines zurückgibt. Wird ignoriert, während eine Anfrage läuft. |
buttonProps | status sowie Pointer- und Fokus-Handler. Spreade sie auf <Button> oder auf alles, was diese Handler zusammensetzt. |
status | "idle" | "loading" | "success" | "error" |
error | Der letzte Ablehnungsgrund. |
reset() | Geht sofort zu idle zurück und ignoriert die laufende Anfrage. |
isPending() | Ob eine Anfrage läuft. |
Button über seine feedback-Prop.