Skip to main content

useProvided

Retrieves a value of type T from the surrounding context and registers the current hook as its dependent, rebuilding the hook whenever that value changes.

ProfileState useProfileState() {
// Group useProvided calls at the top of the hook.
final auth = useProvided<AuthState>(); // <- Rebuilds this hook when AuthState changes

return ProfileState(canEdit: auth.isLoggedIn);
}

Signature

T useProvided<T>();
dynamic useProvidedUnsafe(Type type);

useProvided<T>() looks up the value registered under the type T and returns it. If no such value is available, it throws ProvidedValueNotFoundException.

useProvidedUnsafe does the same lookup for a Type known only at runtime and returns dynamic. Prefer the type-safe useProvided whenever the type is known at compile time.

dynamic readDynamic(Type type) {
// Resolves a value by a Type known only at runtime - the return type is dynamic.
return useProvidedUnsafe(type);
}

The available values depend on the context the hook runs in:

Use cases

  • Consuming a global state from a screen or another global state hook
  • Reading a value handed down by a parent widget through ValueProvider
  • Resolving a service when useInjected<T>() is itself defined as useProvided<Injector>().get()

Because the hook rebuilds when the provided value changes, the new value can drive other hooks - for example, an effect keyed on it:

GreeterState useGreeterState() {
final auth = useProvided<AuthState>();

useEffect(() {
debugPrint('Logged in: ${auth.isLoggedIn}');
return null;
}, [auth.isLoggedIn]); // <- Re-runs only when the provided value changes

return GreeterState(greeting: auth.isLoggedIn ? 'Welcome back' : 'Hello');
}

Caveats

  • Place useProvided calls together at the top of the hook. Grouping the dependencies makes the structure of the hook easier to reason about, and mirrors the ordered dependency list at the app root.

  • useProvided resolves only values from utopia_hooks' own provider mechanism - the container and the in-tree providers. It does not read package:provider or other InheritedWidget-based containers. To consume those, retrieve the BuildContext and read them through it, or re-provide the value with ValueProvider.

  • The lookup throws when the value is missing, which usually means the provider is registered below the consumer, or not at all. The order of registration matters: a state can only depend on states registered before it.

    // DON'T
    final cart = useProvided<CartState>(); // <- Throws if CartState isn't provided above this hook

    When the value may legitimately be absent, read it through the underlying context instead of letting the exception propagate (useBuildContext().getOrNull<T>()).

See also