Skip to main content

useMemoizedFuture

Combines useMemoized and useFuture: it memoizes the Future returned by a factory and listens to it, recreating the Future only when keys change.

Widget buildProfile(BuildContext context, UserService service, String userId) {
// The block runs only when userId changes; no separate useMemoized needed.
final snapshot = useMemoizedFuture(
() => service.loadProfile(userId),
keys: [userId], // <- A new Future is created only when userId changes
);

if (snapshot.hasError) return const Text('Failed to load');
return Text(snapshot.data?.name ?? 'Loading...');
}

Signature

AsyncSnapshot<T> useMemoizedFuture<T>(
Future<T>? Function() block, {
T? initialData,
bool preserveState = true,
HookKeys keys = hookKeysEmpty,
});

T? useMemoizedFutureData<T>(
Future<T>? Function() block, {
T? initialData,
bool preserveState = true,
void Function(Object, StackTrace)? onError,
HookKeys keys = hookKeysEmpty,
});
  • block - factory that produces the Future. It runs on first build and again whenever keys change. Returning null means "no future yet".
  • keys - the useMemoized keys. With the default empty list the block runs exactly once.
  • initialData, preserveState - forwarded to useFuture; see useFuture.

useMemoizedFutureData returns data directly and forwards onError to the built-in error handler.

Profile? useProfile(UserService service, String userId) => useMemoizedFutureData(
() => service.loadProfile(userId),
keys: [userId],
); // <- Returns the value directly; reports errors itself

Use cases

  • Loading data that depends on an argument (a user id, a query) where the request should re-run when that argument changes.
  • Any place you would otherwise write useFuture(useMemoized(..., keys)) - this is the same thing in one call.

Caveats

  • Put every value the block reads into keys. If a captured value is missing from keys, the Future keeps using the value from the build that created it and will not re-run when that value changes. This is the same closure-capture caveat as useMemoized and useEffect.

  • For loading screen data, useAutoComputedState is usually the better tool: it tracks initialization, guards null inputs with shouldCompute, exposes refresh, and carries the error in its value. Reach for useMemoizedFuture when you specifically need raw AsyncSnapshot semantics.

See also