useIsMounted
Returns a function that reports whether the hook's context is still mounted. Call it inside async callbacks before touching state, so updates that resolve after teardown are skipped.
class ProfileLoader extends HookWidget {
final Future<String> Function() load;
const ProfileLoader({super.key, required this.load});
Widget build(BuildContext context) {
final name = useState<String?>(null);
final isMounted = useIsMounted();
useEffect(() {
Future<void> run() async {
final result = await load();
if (isMounted()) name.value = result; // <- Skip the update if torn down
}
unawaited(run());
return null;
}); // <- No keys: runs once on mount
return Text(name.value ?? 'Loading...');
}
}
Signature
IsMounted useIsMounted();
typedef IsMounted = bool Function();
Returns an IsMounted callback. Calling it returns true while the context is alive and false once it has been destroyed. The same callback instance stays valid for the lifetime of the hook, so it is safe to capture in a closure.
Use cases
- Guarding a
useStateupdate that happens after anawait, when the widget may already be gone - Bailing out early from an async loop or a stream handler once the context is torn down
Caveats
-
useIsMountedonly tells you the current state; it does not stop pending work. You still have to check it yourself at the right moment - typically right after eachawait, before writing state.final state = useState(0);final isMounted = useIsMounted();useEffect(() async {await Future.delayed(const Duration(seconds: 1));if (isMounted()) state.value++; // <- Without this guard, setting value after dispose throwsreturn null;}); -
When the value you guard lives in a
useState, prefer its built-insetIfMounted(value)extension - it performs the mounted check and the assignment in one step:// Equivalent, more concise:if (!state.setIfMounted(next)) return;