Skip to content

Lint request : avoid_returning_widgets #58303

Open
@NatoBoram

Description

@NatoBoram

Describe the rule you'd like to see implemented

Include as much detail as you can.

This should include a description of who would use the lint (such as if it's
specific to a framework like Flutter), what conditions the rule should look
for, and what conditions the rule should ignore.

Disallow functions from returning a Widget except in a few exceptions.

  • @override is used
  • It's a type, not an implementation
  • It's an anonymous function

There are many discussions about Functional Widgets vs Stateless Widgets and the consensus is that classes are generally better than functions. I think it would be better to get in the habit of writing widgets instead of functions early in the learning process and a linting rule can help avoid mistakes.

Alternative names : avoid_returning_widgets, avoid_functional_widgets, prefer_widget_classes.

Examples

Ideally, provide motivating examples w/ rationale.

  • Small stateless widgets have a good chance of being able to use a const constructor, which would avoid unnecessary rebuilds.
  • Large widgets are easier to maintain when they are in their own file rather than mixed in with another larger widget.
  • Functional widgets don't show up in the Widget inspector

BAD

class Bad extends StatelessWidget {
  const Bad({Key key}) : super(key: key);

  @override
  Widget build(BuildContext context) => _getExample();

  /// Disallowed.
  Widget _getExample() => const Example();
}
class BadBuilder extends StatelessWidget {
  const BadBuilder({Key key}) : super(key: key);

  @override
  Widget build(BuildContext context) => Builder(builder: _getExample);

  /// Disallowed.
  Widget _getExample(BuildContext context) => const Example();
}

GOOD

class Good extends StatelessWidget {
  const Good({Key key}) : super(key: key);

  /// Allowed because of `@override`.
  @override
  Widget build(BuildContext context) => const Example();
}
class GoodBuilder extends StatelessWidget {
  const GoodBuilder({Key key}) : super(key: key);

  @override
  Widget build(BuildContext context) => Builder(
        builder:

            /// Allowed because it's anonymous.
            (context) => const Example(),
      );
}
/// Allowed because it's not implemented.
typedef WidgetBuilder = Widget Function(BuildContext context);
class Builder extends StatelessWidget {
  const Builder({
    Key key,
    @required this.builder,
  })  : assert(builder != null),
        super(key: key);

  /// Allowed because it's not implemented.
  final WidgetBuilder builder;

  /// Allowed because of `@override`.
  @override
  Widget build(BuildContext context) => builder(context);
}

Additional context

Add any other considerations or context here.

Metadata

Metadata

Assignees

No one assigned

    Labels

    P3A lower priority bug or feature requestarea-devexpFor issues related to the analysis server, IDE support, linter, `dart fix`, and diagnostic messages.devexp-linterIssues with the analyzer's support for the linter packagelinter-lint-requesttype-enhancementA request for a change that isn't a bug

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions