skip to content

Flutter Riverpod

1 roadmap31 questionsupdated

Riverpod 3 declares providers outside the widget tree, reads them through Ref, and caches, disposes and retries them automatically. Interviewers ask what it fixes about Provider.

on this pageshow

guide

overview

~1 min

Riverpod is a state-management and dependency-injection library for Flutter and Dart, written by the author of Provider as its successor. Its state lives in provider objects declared at the top level of a file, outside the widget tree, and code reaches them through a `Ref`. Interviewers use it to test whether you can reason about *where state lives, who depends on it and when it goes away* — and the standard opening question is what Riverpod fixes about Provider: no runtime lookup failure because a provider sits above the wrong widget, no dependence on `BuildContext` for reading state, and several providers of the same type without wrapper classes. The hub follows the life of one piece of state. [Declared provider types](/topics/mob-riverpod-providers) is the vocabulary: which kind of provider fits which job. [Ref watch, read and listen](/topics/mob-riverpod-ref) is how widgets and other providers consume them. [Auto-dispose and families](/topics/mob-riverpod-modifiers) decides how long state survives and how it is keyed. [AsyncValue states](/topics/mob-riverpod-async) is how loading, data and failure reach the screen. [Annotation codegen](/topics/mob-riverpod-codegen) is the `@riverpod` syntax that generates providers for you, and [overrides and containers](/topics/mob-riverpod-testing) is how all of it gets tested. Junior rounds ask you to pick a provider type and explain `watch` against `read`. Middle and senior rounds move to cache lifetimes, refresh behaviour, retries, scoped overrides and migrating a Riverpod 2 codebase. Learn the provider types and `Ref` first; everything else modifies them.

primer

### Providers are declarations, not widgets A provider is a final, usually global, object that describes how to create a value. Declaring it creates nothing: the value comes into being the first time something reads it, inside a **container** that holds every provider's state. In Flutter that container comes from the `ProviderScope` at the root of the app. Because the declaration is plain Dart, a missing provider becomes a compile error instead of a runtime exception, and two providers returning the same type never collide. ### Dependencies form a graph A provider can watch other providers while it builds, so the app's state becomes a graph of derived values. When an upstream value changes, Riverpod rebuilds what depends on it and nothing else. Most design answers come down to drawing that graph: what is the source of truth, what is derived, and which edge causes a rebuild. ### Lifetime is explicit Every provider has a lifetime you choose. **Auto-dispose** ties state to its listeners, which frees memory but can surprise you with a refetch; **keeping alive** trades that back for a cache. A **family** multiplies one declaration into an instance per argument, which makes argument equality a correctness concern rather than a detail. ### Async is a value, not a callback Async providers do not make the UI await a `Future`. They expose an **`AsyncValue`**, a sealed type that is loading, data or error — and can carry the last good data while a new load runs. Screens render from that one value, which is why exhaustive handling and refresh semantics come up so often. ### Mutation goes through notifiers Read-only providers compute; **notifiers** own state that changes. A notifier's `build` produces the starting state and its methods replace it, so every change passes through one class that tests and other providers can reason about. ### Tests swap the graph, not the code Any provider can be **overridden** in a container or scope. A test replaces a repository at the edge of the graph and every provider above it sees the fake, while production code stays untouched and no separate injection framework is needed.

Provider
A top-level object that declares how to create one piece of state or one dependency. It holds no value itself; a container creates and caches the value on first read.
ProviderScope
The Flutter widget, placed at the root of the app, that owns the provider container. A nested scope can override providers for one subtree.
ProviderContainer
The object that stores provider states and their dependency graph. Flutter apps get one from ProviderScope; pure Dart code and unit tests create one directly.
Ref
The handle a provider or notifier receives to read other providers, register dispose callbacks and control its own lifetime.
WidgetRef
The Flutter-side counterpart of Ref, handed to consumer widgets so their build methods and handlers can read providers.
Notifier
A class that owns mutable provider state: build returns the initial state, and its methods assign new state. AsyncNotifier is the async variant.
AsyncValue
A sealed type with AsyncData, AsyncLoading and AsyncError cases, used by async providers so the UI can render every state from one value.
autoDispose
A modifier that destroys a provider's state once nothing listens to it any more, so the next read builds it from scratch.
keepAlive
A way to exempt a provider from auto-disposal, either permanently in its declaration or conditionally from inside its build.
Family
A provider that takes an argument and keeps a separate state per distinct argument value, such as one product per id.
Override
A replacement for a provider's creation logic or value inside one container or scope, used for tests, previews and subtree-specific values.
riverpod_generator
The build_runner code generator that turns functions and classes annotated with @riverpod into providers, deriving their names and kinds.

Start from the root. `ProviderScope` wraps the app and owns one container. When a consumer widget calls `ref.watch` on a provider for the first time, the container runs that provider's build, and the build may itself watch further providers — a repository, a settings value, an auth state. Each watch records an edge in the graph. When a source changes, the container marks its dependants dirty and rebuilds them lazily, and widgets that watch the result rebuild with them. When the last listener of an auto-dispose provider goes away, its state is dropped and its dispose callbacks run. In that picture, provider types decide what a node holds, `Ref` draws the edges, modifiers decide when a node is created, keyed and freed, `AsyncValue` is what async nodes carry to the widget, and overrides replace a node before anything reads it. Codegen only writes the declarations; the runtime graph it produces is the same. The pieces meet in a few lines — a repository at the edge, a notifier that depends on it, and a test that swaps the edge: ```dart final repoProvider = Provider<TodoRepo>((ref) => HttpTodoRepo()); class Todos extends AsyncNotifier<List<Todo>> { @override Future<List<Todo>> build() => ref.watch(repoProvider).fetchAll(); } final todosProvider = AsyncNotifierProvider<Todos, List<Todo>>(Todos.new); // in a test final container = ProviderContainer.test( overrides: [repoProvider.overrideWithValue(FakeTodoRepo())], ); ``` Nothing in `Todos` knows about the fake. That is the property interviewers look for: the dependency is declared once, resolved by the container, and replaceable wherever the graph is built.

  1. Declared Provider Types →

    Start with the kinds of provider and the job each fits; every other section assumes you can pick one.

  2. Ref Watch, Read & Listen →

    How widgets and providers consume state: watch, read and listen, and where each one belongs.

  3. AsyncValue States →

    Most real providers load data, so learn how loading, data and error states reach the screen.

  4. Auto-Dispose & Families →

    Lifetime and keying: auto-dispose, keep-alive caches and families, where leaks and surprise refetches come from.

  5. Overrides & Containers →

    Overrides and containers show why the provider graph makes Riverpod code testable without a widget tree.

  6. Annotation Codegen →

    The @riverpod syntax generates what the earlier sections taught by hand; learn it once the runtime model is clear.

  • Calling ref.read inside a build method to avoid rebuilds: the widget then shows stale state, because read never subscribes.

  • Doing setup in a notifier's constructor instead of build, where ref and state are not yet available.

  • Passing a freshly created list or object as a family argument, so every call misses the cache and builds new state.

  • Being surprised by a refetch after navigating back: auto-dispose dropped the state when the screen's last listener went away.

  • Rendering only the data case of an AsyncValue, or blanking the screen during a refresh that still holds the previous data.

  • Overriding a provider in a nested ProviderScope without declaring dependencies, so providers that watch it never see the override.

  • Answering with Riverpod 2 idioms such as StateNotifierProvider without saying Riverpod 3 moved them to the legacy import.

This guide assumes **Riverpod 3**, where the answers below are written. Many codebases in interviews are still on Riverpod 2, so it helps to know what moved: - **Riverpod 2** introduced `Notifier` and `AsyncNotifier` and the `@riverpod` code generator, and made them the recommended way to hold mutable state. - **Riverpod 3** keeps `StateProvider`, `StateNotifierProvider` and `ChangeNotifierProvider` only as legacy APIs behind a separate import, and expects new code to use notifiers. - **Riverpod 3** added behaviour you may be asked to explain in an incident story: providers that fail while building are retried automatically, and listeners of widgets that are not visible are paused instead of notified. - **Riverpod 3** also shipped experimental APIs, including mutations, which let the UI show whether a save or delete is still running. Treat anything marked experimental as subject to change and say so in an answer. Later 3.x releases changed tooling and testing details, such as how `riverpod_lint` is enabled and how a notifier family is overridden. When an answer depends on one of those, name the minor version.

Riverpod is usually weighed against three neighbours. **Provider**, from the same author, wraps `InheritedWidget` and looks providers up through `BuildContext`; Riverpod exists to remove that coupling. **Bloc** models state as streams of events and states with explicit classes for each, which suits teams that want a strict, ceremony-heavy pattern. Plain `setState` and `InheritedWidget` remain the right answer for state local to one widget. A strong answer names the trade: Riverpod gives dependency injection and caching in one tool, but you pay for it with a dependency graph you have to understand. Around it sit the packages it is commonly used with. `flutter_riverpod` is the Flutter binding and `hooks_riverpod` adds `flutter_hooks` support. `riverpod_generator` and `riverpod_lint` form the codegen and analysis side, and projects that already run `build_runner` for `freezed` or `json_serializable` often adopt the generator alongside them.

explore

report an issue with this guide →

questions

page 1 of 2

In Riverpod 3, what is AsyncValue, and how do you render its loading, data and error states in a Flutter widget?

level: juniorimportance: must knowfreq 64%

answer

  1. sealed, three subclasses
  2. switch needs no default
  3. AsyncData(:final value)
  4. when with three callbacks
  5. value is nullable, not throwing

basics

~10 s

AsyncValue is Riverpod's sealed result type for async providers: AsyncData, AsyncLoading or AsyncError. A widget watches the provider and switches over the AsyncValue - exhaustively, with no default - or calls when(data:, error:, loading:).

solid answer

~40 s

Watching a `FutureProvider`, `StreamProvider` or `AsyncNotifierProvider` returns an `AsyncValue<T>`, not a `T`. `AsyncValue` is a **sealed** class with three concrete subclasses - `AsyncData`, `AsyncLoading` and `AsyncError` - so a Dart 3 `switch` expression over it is exhaustive without a default: `AsyncData(:final value) => FeedList(value)`, `AsyncError(:final error) => ErrorView(error)`, `AsyncLoading() => spinner`. The older callback style, `feed.when(data: ..., error: ..., loading: ...)`, still works. For quick checks there are `value` (nullable), `hasValue`, `hasError` and `isLoading`. In Riverpod 3, `value` never throws: it returns the data, or the previous data during loading or error, or `null` - the old throwing `value` was removed and `valueOrNull` renamed to `value`. You never write `try`/`catch` or an `isLoading` flag yourself.

code

dart · 24 lines
dart
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';

final newsFeedProvider = FutureProvider<List<Article>>((ref) async {
  return ref.watch(newsApiProvider).fetchHeadlines();
});

class NewsFeedPage extends ConsumerWidget {
  const NewsFeedPage({super.key});

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final feed = ref.watch(newsFeedProvider);
    return switch (feed) {
      AsyncData(:final value) => ListView(
          children: [
            for (final article in value) ListTile(title: Text(article.title)),
          ],
        ),
      AsyncError(:final error) => Center(child: Text('Could not load news: $error')),
      AsyncLoading() => const Center(child: CircularProgressIndicator()),
    };
  }
}

go deeper

for a junior

Recall the three states and write the switch with AsyncData, AsyncError and AsyncLoading branches. Know that watching an async provider gives an AsyncValue.

for a middle

Explain why sealing makes the switch exhaustive, compare switch with when, and describe what value, hasValue and isLoading report.

for a senior

Standardise how screens render async state, including error presentation and logging from the stack trace, and remove FutureBuilder duplication.

for a principal

Decide a house style - patterns versus when, shared loading and error widgets - so async screens look and behave consistently across teams.

## What AsyncValue is An **async provider** - `FutureProvider`, `StreamProvider`, `AsyncNotifierProvider`, `StreamNotifierProvider` - does not hand widgets a `Future` or `Stream`. It exposes an `AsyncValue<T>`: a snapshot of the operation's state that the widget can render synchronously on every build. For a news app, `ref.watch(newsFeedProvider)` returns `AsyncValue<List<Article>>`. `AsyncValue` is a **sealed class**. Its concrete subclasses are: | Subclass | Meaning | Key fields | |---|---|---| | `AsyncData<T>` | a value is available | `value` (non-null type `T`) | | `AsyncLoading<T>` | the operation is in progress | `progress` (optional, 0 to 1) | | `AsyncError<T>` | the operation failed | `error`, `stackTrace` | Because the hierarchy is sealed, the Dart analyzer knows these are the only possibilities. ## Rendering with switch The recommended Riverpod 3 style is a Dart 3 `switch` expression: ```dart final feed = ref.watch(newsFeedProvider); return switch (feed) { AsyncData(:final value) => ArticleList(articles: value), AsyncError(:final error) => FeedError(message: '$error'), AsyncLoading() => const Center(child: CircularProgressIndicator()), }; ``` - No `default` branch is needed; forgetting a case is a compile error. - `:final value` destructures the field into a local. - The `AsyncError` branch can also bind `:final stackTrace` for logging. The Riverpod tutorial also shows a property-pattern style - `AsyncValue(:final value?)`, then `AsyncValue(error: != null)`, then `AsyncValue()` - and warns that with that style the order matters: check value first, error second, loading last. ## Rendering with when Before patterns existed, the idiom was a method with three required callbacks: ```dart return feed.when( data: (articles) => ArticleList(articles: articles), error: (error, stackTrace) => FeedError(message: '$error'), loading: () => const Center(child: CircularProgressIndicator()), ); ``` `when` is still in Riverpod 3 and adds flags for multi-state situations such as refreshing. Related helpers: - `maybeWhen` / `whenOrNull` - handle only some cases. - `whenData(cb)` - transform the data and keep loading and error as they are, returning a new `AsyncValue`. ## Quick accessors 1. `value` - the data, or the previous data while loading or after an error, or `null` if there has never been any. 2. `hasValue`, `hasError`, `isLoading` - booleans that can be true at the same time. 3. `error`, `stackTrace` - nullable on the base type. 4. `requireValue` - the data, or throws; for code that is sure data exists. ## What changed in Riverpod 3 - `AsyncValue` became sealed, enabling exhaustive switches. - `valueOrNull` was renamed to `value`; the old `value`, which rethrew errors, was removed. - `AsyncLoading` gained an optional `progress`. ## Common mistakes - Treating `ref.watch(newsFeedProvider)` as the list itself and calling `.length` on it. - Writing a `FutureBuilder` around a provider's future, which re-creates what `AsyncValue` already gives you. - Adding a `default` case, which hides a missing branch from the compiler. ## Choosing between switch and when Both styles produce the same screen for the simple case, and interviewers mostly want to hear that you know why the pattern style is now preferred: - The `switch` is plain Dart: the compiler checks exhaustiveness, and each branch can destructure exactly the fields it needs. - `when` hides multi-state details behind flags, which is convenient but makes it easier to forget what a refresh or an error after data looks like. - A `switch` on the concrete subclasses and a `switch` on properties such as `AsyncValue(:final value?)` behave differently when old data is carried along; pick one style per codebase and document it.

  • How is AsyncValue different from Flutter's AsyncSnapshot?
    Both describe an async result, but `AsyncValue` is produced and cached by the provider rather than by a builder widget, so every widget watching the provider shares one fetch. It is sealed, so switches over it are exhaustive, and it can carry previous data together with a loading or error state, which is what makes stale-while-refreshing screens simple.
  • What does whenData do on an AsyncValue<List<Article>>?
    It maps only the data, for example `feed.whenData((a) => a.length)` gives an `AsyncValue<int>`. Loading and error pass through unchanged, and if the callback throws, the result becomes an `AsyncError`. It is handy for deriving a value while keeping the three-state shape for the widget.

saying these in an interview costs you the question

  • ref.watch on a FutureProvider returns the Future to await in build
  • A switch over AsyncValue needs a default branch to compile
  • In Riverpod 3 value throws when the provider is in error
  • You must wrap provider reads in try/catch to handle failures
  • AsyncValue is an enum with three constants
open as a page

In Riverpod 3 with riverpod_generator, what does annotating a function versus a Notifier class with @riverpod generate, and how is it named?

level: juniorimportance: must knowfreq 55%

basics

~20 s

An annotated function with a Ref first parameter becomes a read-only functional provider whose kind follows its return type; an annotated class extending _$Name with build() becomes a notifier provider. Names are lower camel case plus Provider, with a trailing Notifier stripped.

open as a page

In Riverpod 3, what does autoDispose do, and why does a product-detail screen refetch after you leave and reopen it?

level: juniorimportance: must knowfreq 55%

basics

~20 s

autoDispose destroys a provider's state once nothing listens to it any more. Leaving the product screen removes its last listener, so the state and fetched product are dropped; reopening reads the provider again, which rebuilds it and refetches.

open as a page

In Riverpod 3, which provider type fits a computed value, a one-off async load, a live stream, and state the UI changes?

level: juniorimportance: must knowfreq 60%

basics

~10 s

Provider for a synchronous computed or injected value, FutureProvider for data loaded once, StreamProvider for values that keep arriving, and NotifierProvider or AsyncNotifierProvider when the UI must change the state through methods.

open as a page

In Riverpod 3, what is the difference between ref.watch, ref.read and ref.listen, and where does each one belong?

level: juniorimportance: must knowfreq 78%

basics

~20 s

ref.watch returns a provider's value and subscribes, so the widget or provider rebuilds on change; ref.read returns the current value once with no subscription, for event handlers; ref.listen runs a callback on change for side effects like a snackbar.

open as a page

In Riverpod 3, how do you swap a quiz app's repository provider for a fake in a Flutter widget test?

level: juniorimportance: must knowfreq 58%

basics

~20 s

Wrap the widget given to tester.pumpWidget in a ProviderScope whose overrides list replaces the repository provider, such as quizRepositoryProvider.overrideWithValue(FakeQuizRepository()). Every provider that watches the repository then builds on the fake, with no production code changes.

open as a page

In Riverpod 3, when does riverpod_generator's @riverpod syntax pay off, and when do hand-written providers fit better?

level: middleimportance: must knowfreq 50%

basics

~20 s

Riverpod's docs recommend riverpod_generator only when a project already runs code generation, such as freezed or json_serializable. It buys automatic provider kinds, any parameters, auto-dispose defaults and stateful hot reload, at the cost of a slow build step.

open as a page

In Riverpod 3, how does a Notifier's build() method work, and why must initialization live in build rather than the constructor?

level: middleimportance: must knowfreq 50%

basics

~20 s

build() returns the notifier's initial state and may watch other providers; it re-runs, on the same instance, when one of them changes. The constructor runs before the notifier is attached, so ref and state are unavailable there.

open as a page

In Riverpod 3 unit tests, why use ProviderContainer.test and container.listen rather than a shared container and container.read?

level: middleimportance: must knowfreq 48%

basics

~20 s

ProviderContainer.test creates a fresh container per test and disposes it automatically at the end, so state never leaks. container.listen keeps auto-dispose providers alive during the test and records each change, which container.read alone does not.

open as a page

In flutter_riverpod 3, how do ConsumerWidget, ConsumerStatefulWidget and Consumer each give you a WidgetRef, and when do you pick each?

level: juniorimportance: should knowfreq 58%

basics

~20 s

ConsumerWidget passes a WidgetRef as build's second parameter; ConsumerStatefulWidget's ConsumerState exposes a ref field usable in every State lifecycle; Consumer is a builder widget that hands (context, ref, child) to a small subtree so only it rebuilds.

open as a page

In a Riverpod 3 AsyncNotifier, what does AsyncValue.guard do, and what does state hold if a guarded news-feed refresh fails?

level: middleimportance: should knowfreq 40%

basics

~20 s

AsyncValue.guard runs an async callback and returns AsyncData on success or AsyncError on failure, replacing try/catch. After a failed guarded refresh, state is an AsyncError that still carries the previously loaded articles as its value.

open as a page

In Riverpod 3, what does a news feed's AsyncValue contain while it refreshes, and how do isRefreshing and skipLoadingOnRefresh keep old articles visible?

level: middleimportance: should knowfreq 44%

basics

~20 s

After invalidate or refresh, the AsyncValue stays AsyncData holding the old articles with isLoading and isRefreshing true, and when() shows data because skipLoadingOnRefresh defaults to true. A watched dependency change instead yields AsyncLoading with the old value (isReloading).

open as a page

With riverpod_generator, how do extra parameters on a @riverpod function or a Notifier's build method turn a provider into a family?

level: middleimportance: should knowfreq 40%

basics

~20 s

Any parameter after the Ref of an annotated function, or any build() parameter of an annotated Notifier, makes the generated provider a family whose call mirrors that parameter list, including named, optional and defaulted parameters and type parameters.

open as a page

With riverpod_generator, why is a @riverpod provider disposed once nothing listens to it, and what does @Riverpod(keepAlive: true) change?

level: middleimportance: should knowfreq 42%

basics

~10 s

riverpod_generator makes providers auto-dispose by default, because the annotation's keepAlive field defaults to false. @Riverpod(keepAlive: true) generates a provider that is not auto-disposed, matching a hand-written provider declared without autoDispose.

open as a page

In Riverpod 3, how does .family give each product id its own state, and why must the argument have a consistent == and hashCode?

level: middleimportance: should knowfreq 50%

basics

~20 s

A family turns one provider definition into a map of independent providers keyed by the argument. Riverpod finds the existing instance by == and hashCode, so an argument without value equality, like a fresh list, creates a new state on every call.

open as a page

In Riverpod 3, how would you cache an autoDispose product-detail provider for five minutes while never caching a failed request?

level: middleimportance: should knowfreq 36%

basics

~20 s

Keep the provider autoDispose, call ref.keepAlive() only after the fetch succeeds, and close the returned KeepAliveLink from a five-minute Timer cancelled in onDispose. A failed fetch throws before keepAlive, so its error is disposed normally.

open as a page

In Riverpod 3, when do you choose AsyncNotifierProvider over FutureProvider, and how do an AsyncNotifier's build, state, future and update work?

level: middleimportance: should knowfreq 45%

basics

~20 s

Choose AsyncNotifierProvider when asynchronously loaded state must also be changed, like a user profile the user can rename. build() loads it, state is an AsyncValue, future resolves to the first non-loading value, and update() changes data without passing through loading.

open as a page

With Riverpod 3, how does StreamProvider expose a live unread-notifications count, and what does a widget get from ref.watch on it?

level: middleimportance: should knowfreq 35%

basics

~20 s

StreamProvider subscribes to the stream its function returns and exposes the latest event as AsyncValue<int>: loading until the first event, then data, or error if the stream emits one. All widgets watching it share that subscription.

open as a page

In Riverpod 3, what is the difference between ref.invalidate and ref.refresh, and when would you pass asReload: true?

level: middleimportance: should knowfreq 42%

basics

~20 s

ref.invalidate discards a provider's state now and lets it rebuild later, coalescing repeated calls; ref.refresh is invalidate followed by read, rebuilding immediately and returning the new value. asReload: true makes an async provider drop its previous data while reloading.

open as a page

In Riverpod 3, how does provider.select narrow a widget's rebuilds, and what does it not save you from?

level: middleimportance: should knowfreq 46%

basics

~20 s

provider.select(fn) makes ref.watch or ref.listen react only when fn's result changes by ==. The upstream provider still recomputes and the selector still runs on every change; returning a freshly built list or object each time defeats it.

open as a page

In Riverpod 3, how do overrideWith, overrideWithValue and overrideWithBuild differ when you override a provider?

level: middleimportance: should knowfreq 40%

basics

~10 s

overrideWith replaces a provider's create function and keeps full Ref access; overrideWithValue replaces its result, taking an AsyncValue for Future and Stream providers; overrideWithBuild swaps only a Notifier's build while keeping its real methods.

open as a page

In Riverpod 3, how does AsyncValue.requireValue let a provider combine two async providers without await, and when is it dangerous inside a widget?

level: seniorimportance: should knowfreq 28%

basics

~20 s

requireValue returns the data if any exists, rethrows the error wrapped in ProviderException, or throws AsyncValueIsLoadingException while loading. Inside a FutureProvider or AsyncNotifier that loading exception is silenced, so ref.watch(a).requireValue combines providers synchronously; in a widget it crashes the build.

open as a page

Migrating a fitness app's hand-written Riverpod 3 providers to @riverpod, what behaviour changes and what breaks at the call sites?

level: seniorimportance: should knowfreq 30%

basics

~20 s

Generated providers auto-dispose by default, so state that relied on staying alive now resets; names are derived, so call sites and overrides change; families take real parameter lists; and legacy StateNotifier or ChangeNotifier providers must be rewritten, since codegen does not generate them.

open as a page

In Riverpod 3, a product-detail FutureProvider keeps retrying while the device is offline; what is the default retry policy, and how do you customise or disable it?

level: seniorimportance: should knowfreq 30%

basics

~20 s

Riverpod 3 retries a provider that throws while building: up to 10 times, starting at 200 ms and doubling to a 6.4 s cap, skipping Error subclasses and ProviderException. Pass retry: to the provider or to ProviderScope; returning null stops retrying.

open as a page

Your Riverpod 2 codebase uses StateProvider and StateNotifierProvider; what does Riverpod 3 do with them, and how do you migrate them to Notifier?

level: seniorimportance: should knowfreq 35%

basics

~10 s

Riverpod 3 keeps StateProvider and StateNotifierProvider but moves them to legacy.dart as discouraged. Migrate each to a Notifier: initial state and watched dependencies go into build(), methods assign state, and callers switch to NotifierProvider.

open as a page

A Riverpod 3 FutureProvider that watches the currency setting sometimes throws UnmountedRefException after an await when the user switches currency mid-request; what is happening and how do you fix it?

level: seniorimportance: should knowfreq 34%

basics

~20 s

Switching currency rebuilds the provider with a new Ref, so the closure still awaiting from the previous build holds a disposed Ref; using it throws UnmountedRefException. Cancel the work in ref.onDispose, or check ref.mounted after each await.

open as a page

In Riverpod 3, how does overriding a provider in a nested ProviderScope scope it to a subtree, and why must it declare dependencies?

level: seniorimportance: should knowfreq 28%

basics

~20 s

A nested ProviderScope creates a child container whose overrides apply only to its subtree. A provider opts into scoping by declaring dependencies, and every provider watching it must list it, or that dependant stays in the root container and never sees the override.

open as a page

In Riverpod 3, what are the experimental mutations, and how would you show a spinner on a news article's bookmark button while the save runs?

level: middleimportance: nice to knowfreq 18%

basics

~20 s

Mutations are an experimental Riverpod 3 API for tracking a side effect's progress outside provider state. A Mutation keyed per article is watched for MutationIdle/Pending/Success/Error and started with run(ref, (tsx) async ...), so the button shows a spinner while pending.

open as a page

What does Riverpod's riverpod_lint package catch in @riverpod code, and how is it enabled in current Riverpod 3 projects?

level: middleimportance: nice to knowfreq 22%

basics

~10 s

riverpod_lint adds Riverpod-specific warnings, quick fixes and assists to the Dart analyzer. Since 3.1.0 it runs on analysis_server_plugin, enabled under plugins: in analysis_options.yaml, and checks the codegen contract plus general Riverpod mistakes.

open as a page

In Riverpod 3, what happens to a product list's provider listeners while a product-detail route covers the list, and how does pausing differ from disposal?

level: middleimportance: nice to knowfreq 24%

basics

~20 s

Riverpod 3 pauses the ref.watch subscriptions of consumers whose TickerMode is off, as on a route hidden under an opaque one. The provider keeps its state and is not disposed, even if autoDispose, but stops notifying them until they resume.

open as a page

showing 1–30 of 31