Description
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.
- Why should I ever use stateless widgets instead of functional widgets? flutter/flutter#19269
- https://flutter.dev/docs/perf/rendering/best-practices#controlling-build-cost
- feat: lint when widgets are being returned outside the build method dart-archive/linter#2582 (comment)
- https://stackoverflow.com/q/53234825/5083247
- https://youtu.be/IOyq-eTRhvo
- https://www.reddit.com/r/FlutterDev/comments/mp4xpx/comment/gu8j6cz