avoid-ref-watch-outside-build
- Group
- Correctness
- Path
lint/correctness/avoid-ref-watch-outside-build- Default
- On (recommended)
- Origin
- Falcon
- Domain
- riverpod
- Rule
- 126 of 512
Flags Riverpod WidgetRef.watch subscriptions outside synchronous widget build bodies.
Subscriptions belong in build; event callbacks and other widget methods should read once. Consumer builders and package-confirmed Flutter builder, itemBuilder and separatorBuilder callbacks inside build are build contexts. Provider Ref callbacks are left unchanged, including those inside widgets.
Invalid
import 'package:flutter/widgets.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart' as hooks;
final countProvider = Provider<int>((ref) => 0);
class Screen extends ConsumerWidget {
void action(WidgetRef ref) { ref.watch(countProvider); }
int getCount(WidgetRef reader) => reader.watch(countProvider);
Object build(Object context, WidgetRef ref) {
final callback = () => ref.watch(countProvider);
void local() { ref.watch(countProvider); }
return callback;
}
}
class ScreenState extends ConsumerState<Object> {
void initState() { ref.watch(countProvider); }
Object build(Object context) => 0;
}
void action(WidgetRef reader) { reader.watch(countProvider); }
class HookScreen extends hooks.HookConsumerWidget {
Object build(Object context, WidgetRef ref) => 0;
void action(hooks.WidgetRef ref) { ref.watch(countProvider); }
}
class MenuScreen extends ConsumerWidget {
Object build(Object context, WidgetRef ref) =>
PopupMenuButton(itemBuilder: (context) => ref.watch(countProvider));
}class Screen extends ConsumerWidget { void action(WidgetRef ref) { ref.watch(countProvider); } void action(WidgetRef ref) { ref.watch(countProvider); } int getCount(WidgetRef reader) => reader.watch(countProvider); Object build(Object context, WidgetRef ref) { final callback = () => ref.watch(countProvider); final callback = () => ref.watch(countProvider); void local() { ref.watch(countProvider); }class ScreenState extends ConsumerState<Object> { void initState() { ref.watch(countProvider); }}void action(WidgetRef reader) { reader.watch(countProvider); } Object build(Object context, WidgetRef ref) => 0; void action(hooks.WidgetRef ref) { ref.watch(countProvider); } Object build(Object context, WidgetRef ref) => PopupMenuButton(itemBuilder: (context) => ref.watch(countProvider));Valid
import 'package:flutter_hooks/flutter_hooks.dart' as flutter_hooks;
import 'package:flutter/widgets.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart' as hooks;
final countProvider = Provider<int>((ref) => 0);
class Screen extends ConsumerWidget {
Object build(Object context, WidgetRef ref) {
final value = ref.watch(countProvider);
return value;
}
int action(WidgetRef ref) => ref.read(countProvider);
}
class ScreenState extends ConsumerState<Object> {
Object build(Object context) => ref.watch(countProvider);
}
final dependent = Provider<int>((ref) => ref.watch(countProvider));
Object consumer() => Consumer(builder: (context, ref, child) => ref.watch(countProvider));
class Unrelated { int watch(Object value) => 0; }
int unrelated(Unrelated ref) => ref.watch(countProvider);
int unknown(dynamic ref) => ref.watch(countProvider);
class BuilderScreen extends ConsumerWidget {
static final dependent = Provider<int>((Ref ref) => ref.watch(countProvider));
Object build(Object context, WidgetRef ref) =>
Builder(builder: (context) => ref.watch(countProvider));
}
class SliverBuilderScreen extends ConsumerWidget {
Object build(Object context, WidgetRef ref) =>
SliverChildBuilderDelegate((context, index) => ref.watch(countProvider));
}
class OtherBuilders extends hooks.HookConsumerWidget {
Object build(Object context, WidgetRef ref) {
SliverList.builder(itemBuilder: (context, index) => ref.watch(countProvider));
SliverGrid.builder(itemBuilder: (context, index) => ref.watch(countProvider));
ReorderableListView.builder(itemBuilder: (context, index) => ref.watch(countProvider));
AnimatedList(itemBuilder: (context, index, animation) => ref.watch(countProvider));
return flutter_hooks.HookBuilder(builder: (context) => ref.watch(countProvider));
}
}Configure avoid-ref-watch-outside-build
Set its severity in falcon.json. See the configuration guide.
{
"linter": {
"rules": {
"correctness": {
"avoid-ref-watch-outside-build": "error"
}
}
}
}Or silence one occurrence with a suppression comment; the reason is required.
// falcon-ignore lint/correctness/avoid-ref-watch-outside-build: <reason>More correctness rules
- avoid-relative-lib-imports
avoid_relative_lib_importsrecommendedDisallow relative imports that reach into a
lib/directory. - avoid-returning-widgets
avoid-returning-widgetsflutterDisallow functions and methods that return a
Widget. - avoid-type-to-string
avoid_type_to_stringrecommendedAvoid
Type.toString()in production code, where type names may be minified. - avoid-uncaught-future-errorsrecommended
Flags local futures first awaited after another await inside a try/catch.
- avoid-unconditional-break
Reports unconditional break, continue, return or throw in a for-loop body.
- avoid-undisposed-instancesrecommendedflutter
Warns when a disposable constructor result is discarded.
- avoid-unmodified-loop-conditionrecommended
Flags loop conditions whose local scalar inputs are never modified by the loop.
- avoid-unnecessary-setstaterecommendedflutter
Avoid setState during build, initState, or didUpdateWidget.