One-shot operations as first-class state, with declarative listeners.
More in Github .
An Action is a tiny piece of reactive state that represents a single imperative operation — logging in, completing a purchase, deleting a row. It exposes four observable states ( idle , loading , success , error ) and lets the UI subscribe to lifecycle callbacks ( onSuccess , onError , onLoading ) instead of awaiting futures and wrapping them in try/catch .
This pattern is directly inspired by React Query's useMutation . If you've ever written:
const { mutate , isLoading } = useMutation ( login , { onSuccess : () => navigate ( " /home " ), onError : ( e ) => toast . error ( e . message ), });
Enter fullscreen mode
Exit fullscreen mode
…this is the Riverpod equivalent.
The Problem
Async operations triggered by the user (button taps, form submits) don't fit AsyncValue cleanly:
No idle state. AsyncValue starts in loading . But a login screen isn't loading until the user taps the button — it's idle .…