use-ref-and-state-synchronously
Warns when a notifier's ref or state are called past an await point (also known as asynchronous gap).
Using ref or state after an async gap will lead to UnmountedRefException if the notifier is already unmounted.
Try checking for ref.mounted before using ref or state.
Example
❌ Bad:
class CountNotifier extends _$CountNotifier {
int build() => 0;
Future<void> incrementDelayed() async {
await Future<void>.delayed(const Duration(seconds: 1));
// LINT: Avoid accessing 'ref' or 'state' past an await point without checking if the ref is mounted.
state += 1;
}
}
class MyWidget extends StatelessWidget {
const MyWidget({super.key});
Widget build(BuildContext context) => GestureDetector(
child: const Text('show dialog'),
onTap: () => showDialog(
context: context,
builder: (context) => Consumer(
builder: (context, ref, _) => AlertDialog(
actions: [
GestureDetector(
child: const Text('increment and close'),
onTap: () {
ref.read(countProvider.notifier).incrementDelayed();
Navigator.of(context).pop();
},
),
],
),
),
),
);
}
✅ Good:
class CountNotifier extends _$CountNotifier {
int build() => 0;
Future<void> incrementDelayed() async {
await Future<void>.delayed(const Duration(seconds: 1));
if (ref.mounted) {
state += 1;
}
}
}
class MyWidget extends StatelessWidget {
const MyWidget({super.key});
Widget build(BuildContext context) => GestureDetector(
child: const Text('show dialog'),
onTap: () => showDialog(
context: context,
builder: (context) => Consumer(
builder: (context, ref, _) => AlertDialog(
actions: [
GestureDetector(
child: const Text('increment and close'),
onTap: () {
ref.read(countProvider.notifier).incrementDelayed();
Navigator.of(context).pop();
},
),
],
),
),
),
);
}