use-ref-and-state-synchronously
- Group
- Correctness
- Path
lint/correctness/use-ref-and-state-synchronously- Default
- On (recommended)
- Origin
- Falcon
- Domain
- riverpod
- Rule
- 499 of 512
Flags notifier ref and state accesses after an async gap without ref.mounted.
A notifier may be disposed while its asynchronous method is suspended. Guard subsequent accesses with ref.mounted. Only Riverpod 3 AnyNotifier-declared ref and state members are checked; older APIs without ref.mounted, shadowed locals, unrelated classes, and mounted checks themselves are excluded. Nested function bodies form independent async boundaries.
Invalid
import 'package:flutter_riverpod/flutter_riverpod.dart';
final provider = Object();
Future<void> pause() async {}
abstract class Count extends Notifier<int> {
Future<void> increment() async {
await pause();
state += 1;
}
Future<void> explicitThis() async {
await pause();
this.state = 2;
}
Future<void> read() async {
await pause();
ref.read(provider);
}
Future<void> staleGuard() async {
if (!ref.mounted) return;
await pause();
state = 3;
}
Future<void> secondGap() async {
await pause();
if (!ref.mounted) return;
await pause();
state = 4;
}
}
abstract class AsyncCount extends AsyncNotifier<int> {
Future<void> increment() async {
await pause();
state = 5;
}
}
abstract class StreamCount extends StreamNotifier<int> {
Future<void> increment() async {
await pause();
state = 6;
}
} await pause(); state += 1; await pause(); this.state = 2; await pause(); ref.read(provider); await pause(); state = 3; await pause(); state = 4; await pause(); state = 5; await pause(); state = 6;Valid
import 'package:flutter_riverpod/flutter_riverpod.dart';
final provider = Object();
Future<void> pause() async {}
abstract class Count extends Notifier<int> {
Future<void> beforeAwait() async {
state += 1;
await pause();
}
Future<void> guarded() async {
await pause();
if (ref.mounted) state += 1;
}
Future<void> earlyReturn() async {
await pause();
if (!ref.mounted) return;
state += 1;
ref.read(provider);
}
Future<void> explicitGuard() async {
await pause();
if (!this.ref.mounted) return;
this.state = 1;
}
Future<void> shortCircuit() async {
await pause();
if (ref.mounted && state > 0) state = 2;
}
Future<void> shadowed() async {
int state = 1;
await pause();
state += 1;
}
Future<void> nested() async {
await pause();
void callback() { state = 1; }
callback();
}
Future<void> parenthesizedGuard() async {
await pause();
if (!(ref).mounted) return;
state = 1;
}
}
class Unrelated {
int state = 0;
Future<void> update() async {
await pause();
state += 1;
}
}
abstract class OlderNotifier extends BuildlessNotifier<int> {
Future<void> update() async {
await pause();
state = 1;
}
}
const alive = true;
abstract class ConstantGuard extends Notifier<int> {
Future<void> update() async {
await pause();
if (ref.mounted == alive) state = 1;
}
Future<void> parenthesized() async {
await pause();
if (ref.mounted == (alive)) state = 1;
}
Future<void> nestedParenthesized() async {
await pause();
if (ref.mounted == ((alive))) state = 1;
}
}Configure use-ref-and-state-synchronously
Set its severity in falcon.json. See the configuration guide.
{
"linter": {
"rules": {
"correctness": {
"use-ref-and-state-synchronously": "error"
}
}
}
}Or silence one occurrence with a suppression comment; the reason is required.
// falcon-ignore lint/correctness/use-ref-and-state-synchronously: <reason>More correctness rules
- use-ref-read-synchronouslyrecommendedriverpod
Flags Riverpod WidgetRef.read calls after an async gap without a mounted guard.
- use-setstate-synchronouslyrecommendedflutter
Require a mounted check before calling setState after an async gap.
- valid-regexps
valid_regexpsrecommendedDisallow statically known invalid
dart:coreregular expressions. - void-checks
void_checksrecommendedDon't pass or assign values to
void(orFutureOr<void>) locations. - add-equatable-propsrecommendedequatable
Flags concrete Equatable subclasses that do not declare an instance props property.
- always-pass-global-keyflutter
Keep
GlobalKeysstable and pass owned State fields to widgets. - always-remove-listenerrecommendedflutter
Requires Flutter Listenable registrations in State to be removed.
- always-use-package-imports
always_use_package_importsDisallow relative imports in libraries under a package's
lib/directory.