avoid-calling-notifier-members-inside-build

Path
lint/correctness/avoid-calling-notifier-members-inside-build
Default
On (recommended)
Origin
Falcon
Domain
riverpod
Rule
27 of 512
recommendedriverpod

Flags calls to Riverpod notifier methods during widget build.

Build must not trigger notifier side effects. Method tear-offs and nested callbacks are not calls during build; unrelated same-named types and Object methods (toString and noSuchMethod) are ignored.

Invalid

example.dartdart
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart' as hooks;
final countProvider = Provider<int>((ref) => 0);
class Counter extends Notifier<int> { void increment() {} void reset() {} int get value => 0; }
class AsyncCounter extends AsyncNotifier<int> { void refresh() {} }
final counterProvider = Provider<Counter>((ref) => Counter());
final asyncProvider = Provider<AsyncCounter>((ref) => AsyncCounter());
class Screen extends ConsumerWidget {
  Object build(Object context, WidgetRef ref) {
    ref.read(counterProvider).increment();
    final counter = ref.watch(counterProvider);
    counter.increment();
    counter.reset();
    ref.watch(asyncProvider).refresh();
    return 0;
  }
}
class Arrow extends ConsumerWidget {
  Object build(Object context, WidgetRef ref) {
    ref.read(counterProvider).increment();
    return 0;
  }
}
Object consumer() => Consumer(builder: (context, ref, child) {
  ref.read(counterProvider).increment();
  return 0;
});
class HookScreen extends hooks.HookConsumerWidget {
  Object build(Object context, hooks.WidgetRef ref) {
    ref.read(counterProvider).increment();
    return 0;
  }
}
Do not invoke notifier methods during build; move the action to a callback.
9 Object build(Object context, WidgetRef ref) {
10 ref.read(counterProvider).increment();
Do not invoke notifier methods during build; move the action to a callback.
11 final counter = ref.watch(counterProvider);
12 counter.increment();
Do not invoke notifier methods during build; move the action to a callback.
12 counter.increment();
13 counter.reset();
Do not invoke notifier methods during build; move the action to a callback.
13 counter.reset();
14 ref.watch(asyncProvider).refresh();
Do not invoke notifier methods during build; move the action to a callback.
19 Object build(Object context, WidgetRef ref) {
20 ref.read(counterProvider).increment();
Do not invoke notifier methods during build; move the action to a callback.
24Object consumer() => Consumer(builder: (context, ref, child) {
25 ref.read(counterProvider).increment();
Do not invoke notifier methods during build; move the action to a callback.
29 Object build(Object context, hooks.WidgetRef ref) {
30 ref.read(counterProvider).increment();

Valid

example.dartdart
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 Counter extends Notifier<int> { void increment() {} void reset() {} int get value => 0; }
class AsyncCounter extends AsyncNotifier<int> { void refresh() {} }
final counterProvider = Provider<Counter>((ref) => Counter());
final asyncProvider = Provider<AsyncCounter>((ref) => AsyncCounter());
class Service { void increment() {} }
class Screen extends ConsumerWidget {
  Object build(Object context, WidgetRef ref) {
    final counter = ref.watch(counterProvider);
    final callback = () => counter.increment();
    void local() { counter.reset(); }
    final tearoff = counter.increment;
    final service = Service();
    service.increment();
    counter.toString();
    return callback;
  }
  void action(WidgetRef ref) { ref.read(counterProvider).increment(); }
}
void outside(Counter counter) { counter.increment(); }
class Unrelated {
  Object build(Object context, Counter counter) { counter.increment(); return 0; }
}
class DeferredMenu extends ConsumerWidget {
  Object build(Object context, WidgetRef ref) =>
      PopupMenuButton(itemBuilder: (context) {
        ref.read(counterProvider).increment();
        return 0;
      });
}

Configure avoid-calling-notifier-members-inside-build

Set its severity in falcon.json. See the configuration guide.

falcon.jsonjson
{
  "linter": {
    "rules": {
      "correctness": {
        "avoid-calling-notifier-members-inside-build": "error"
      }
    }
  }
}

Or silence one occurrence with a suppression comment; the reason is required.

example.dartdart
// falcon-ignore lint/correctness/avoid-calling-notifier-members-inside-build: <reason>