Skip to main content

ProviderWidget

Provides values to a subtree so descendants can read them with useProvided. ValueProvider provides a single already-computed value; HookProvider provides the result of a hook; ProviderWidget is the low-level InheritedModel both build on.

class App extends StatelessWidget {
final RouterState routerState;

const App({super.key, required this.routerState});


Widget build(BuildContext context) {
// Provides an already-computed value to the subtree below.
return ValueProvider(
routerState, // <- Resolved by useProvided<RouterState>() in any descendant
child: const HomeScreen(),
);
}
}

Any descendant resolves it the usual way:

class HomeScreen extends HookWidget {
const HomeScreen({super.key});


Widget build(BuildContext context) {
final router = useProvided<RouterState>(); // <- Reads the provided value

return Text(router.initialRoute);
}
}

Use cases

  • Reach for ValueProvider when the value is already in hand - a constant, configuration, or an object a parent computed - and no hook needs to run to produce it.
  • Reach for HookProvider when the value comes from a hook, so it re-provides as the hook rebuilds, scoped to one part of the tree rather than registered globally.
  • Reach for ProviderWidget only to provide several values at once under custom keys; in app code prefer the two wrappers above.

ValueProvider

Provides a single value of type T to the subtree, keyed by T.

const ValueProvider<T>(T value, {required Widget child, Key? key});

Use it for values that don't need a hook: constants, configuration, or an already-computed object handed down from a parent. For reactive app-wide state, register a hook in a HookProviderContainerWidget instead.

HookProvider

Runs use as a hook and provides its result to the subtree, re-providing a fresh value whenever it rebuilds.

const HookProvider<T>(T Function() use, {required Widget child, Key? key});
class ShopSection extends StatelessWidget {
const ShopSection({super.key});


Widget build(BuildContext context) {
// Runs useCartState as a hook and provides its result to the subtree.
return const HookProvider(
useCartState, // <- A hook; re-provides a fresh value whenever it rebuilds
child: HomeScreen(),
);
}
}

HookProvider is a HookWidget, so use runs in a real hook context and may call other hooks. It scopes a piece of hook-driven state to one part of the tree, rather than registering it globally at the root.

ProviderWidget

The InheritedModel<Object> that backs both providers above. It holds a Map<Object, Object?> and notifies only the dependents whose key changed.

const ProviderWidget(Map<Object, Object?> values, {required Widget child, Key? key});

Reach for ValueProvider and HookProvider in app code; use ProviderWidget directly only when providing several values at once under custom keys.

Caveats

  • (All three) These widgets feed useProvided and the BuildContext provider lookup - they do not interoperate with package:provider. A value provided here is not visible to Provider.of, and vice versa.

  • (ValueProvider) It keys the value by its static type T. Providing a subtype under a supertype variable provides it under the variable's type, which may not be what a consumer requests.

    // CAREFUL
    final Object config = AppConfig();
    ValueProvider(config, child: child); // <- Provided as Object, not AppConfig
  • (HookProvider) A consumer rebuilds only when the value it depends on changes, and that is driven by the hook: the provided value updates whenever the hook rebuilds and produces a value not equal (via ==) to the previous one.

See also