avoid-unnecessary-consumer-widgets

Path
lint/performance/avoid-unnecessary-consumer-widgets
Default
Off, opt in
Origin
Falcon
Domain
riverpod
Rule
158 of 512
riverpod

Flags Riverpod consumer widgets whose build reference is unused. A direct ConsumerWidget or HookConsumerWidget subclass can use a regular widget when it does not need its WidgetRef. References are matched to the parameter declaration, so nested consumers with their own ref do not count. Abstract/generic classes, mixins, interfaces, missing bodies and uncertain reference types are excluded, as are locally subclassed widgets and helpers that use a WidgetRef parameter.

Invalid

example.dartdart
import 'package:flutter/widgets.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart' as hooks;

final provider = Object();

class PlainConsumer extends ConsumerWidget {
  Widget build(BuildContext context, WidgetRef ref) => const SizedBox();
}

class HookConsumer extends hooks.HookConsumerWidget {
  Widget build(BuildContext context, WidgetRef ref) {
    return const SizedBox();
  }
}

class NestedConsumer extends ConsumerWidget {
  Widget build(BuildContext context, WidgetRef ref) {
    return Consumer(builder: (context, ref, child) {
      ref.watch(provider);
      return const SizedBox();
    });
  }
}

class LocalShadow extends ConsumerWidget {
  Widget build(BuildContext context, WidgetRef ref) {
    {
      final ref = 'a local string';
      print(ref);
    }
    return const SizedBox();
  }
}

class RenamedReference extends ConsumerWidget {
  Widget build(BuildContext context, WidgetRef unused) => const SizedBox();
}

class ClosureShadow extends ConsumerWidget {
  Widget build(BuildContext context, WidgetRef ref) {
    void visit(String ref) { print(ref); }
    visit('shadow');
    return const SizedBox();
  }
}

class PrefixedConsumer extends hooks.ConsumerWidget {
  Widget build(BuildContext context, hooks.WidgetRef reference) => const SizedBox();
}
This widget does not use its `ref`; convert it to a `StatelessWidget`.
6
7class PlainConsumer extends ConsumerWidget {
This widget does not use its `ref`; convert it to a `HookWidget`.
10
11class HookConsumer extends hooks.HookConsumerWidget {
This widget does not use its `ref`; convert it to a `StatelessWidget`.
16
17class NestedConsumer extends ConsumerWidget {
This widget does not use its `ref`; convert it to a `StatelessWidget`.
25
26class LocalShadow extends ConsumerWidget {
This widget does not use its `ref`; convert it to a `StatelessWidget`.
35
36class RenamedReference extends ConsumerWidget {
This widget does not use its `ref`; convert it to a `StatelessWidget`.
39
40class ClosureShadow extends ConsumerWidget {
This widget does not use its `ref`; convert it to a `StatelessWidget`.
47
48class PrefixedConsumer extends hooks.ConsumerWidget {

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 provider = Object();

class WatchesProvider extends ConsumerWidget {
  Widget build(BuildContext context, WidgetRef ref) {
    ref.watch(provider);
    return const SizedBox();
  }
}

class CapturesReference extends ConsumerWidget {
  Widget build(BuildContext context, WidgetRef ref) {
    void callback() { ref.read(provider); }
    callback();
    return const SizedBox();
  }
}

class PassesReference extends ConsumerWidget {
  Widget build(BuildContext context, WidgetRef ref) => render(ref);
  Widget render(WidgetRef reference) {
    reference.watch(provider);
    return const SizedBox();
  }
}

class HelperConsumesReference extends ConsumerWidget {
  Widget build(BuildContext context, WidgetRef ref) => const SizedBox();
  Widget render(WidgetRef reference) {
    reference.watch(provider);
    return const SizedBox();
  }
}

class HookReadsProvider extends hooks.HookConsumerWidget {
  Widget build(BuildContext context, WidgetRef reference) {
    reference.read(provider);
    return const SizedBox();
  }
}

mixin Behavior {}
class MixedConsumer extends ConsumerWidget with Behavior {
  Widget build(BuildContext context, WidgetRef ref) => const SizedBox();
}

abstract class AbstractConsumer extends ConsumerWidget {
  Widget build(BuildContext context, WidgetRef ref) => const SizedBox();
}

class InferredReference extends ConsumerWidget {
  Widget build(BuildContext context, ref) => const SizedBox();
}

class UncertainHelper extends ConsumerWidget {
  Widget build(BuildContext context, WidgetRef ref) => const SizedBox();
  void helper(ref) { print(ref); }
}

Configure avoid-unnecessary-consumer-widgets

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

falcon.jsonjson
{
  "linter": {
    "rules": {
      "performance": {
        "avoid-unnecessary-consumer-widgets": "error"
      }
    }
  }
}

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

example.dartdart
// falcon-ignore lint/performance/avoid-unnecessary-consumer-widgets: <reason>