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 theFuture. It runs on first build and again wheneverkeyschange. Returningnullmeans "no future yet".keys- theuseMemoizedkeys. With the default empty list theblockruns exactly once.initialData,preserveState- forwarded touseFuture; 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
blockreads intokeys. If a captured value is missing fromkeys, theFuturekeeps 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 asuseMemoizedanduseEffect. -
For loading screen data,
useAutoComputedStateis usually the better tool: it tracks initialization, guards null inputs withshouldCompute, exposesrefresh, and carries the error in its value. Reach foruseMemoizedFuturewhen you specifically need rawAsyncSnapshotsemantics.
See also
- useFuture - the underlying hook and its
AsyncSnapshotsemantics - useMemoized - the caching half of this hook
- useAutoComputedState - the higher-level choice for loading data
- useMemoizedStream - the same pattern for a
Stream