What is the difference between functions and classes to create widgets?

  • A+

I have realized that it is possible to create widgets using plain functions instead of subclassing StatelessWidget. An example would be this:

Widget function({ String title, VoidCallback callback }) {   return GestureDetector(     onTap: callback,     child: // some widget   ); } 

This is interesting because it requires far less code than a full-blown class. Example:

class SomeWidget extends StatelessWidget {   final VoidCallback callback;   final String title;    const SomeWidget({Key key, this.callback, this.title}) : super(key: key);    @override   Widget build(BuildContext context) {       return GestureDetector(         onTap: callback,         child: // some widget       );   } } 

So I've been wondering: Is there any difference besides syntax between functions and classes to create widgets? And is it a good practice to use functions?


TDLR: Never ever use functions over classes to make reusable widget-tree. Always extract these into a StatelessWidget instead.

There is a huge difference between using functions instead of classes, that is: The framework is unaware of functions, but can see classes.

Consider the following "widget" function:

Widget functionWidget({ Widget child}) {   return Container(child: child); } 

used this way:

functionWidget(   child: functionWidget(), ); 

And it's class equivalent:

class ClassWidget extends StatelessWidget {   final Widget child;    const ClassWidget({Key key, this.child}) : super(key: key);    @override   Widget build(BuildContext context) {     return Container(       child: child,     );   } } 

used like that:

new ClassWidget(   child: new ClassWidget(), ); 

On paper, both seems to do exactly the same thing: Create 2 Container, with one nested into the other. But the reality is slightly different.

In the case of functions, the generated widget tree looks like this:

Container   Container 

While with classes, the widget tree is:

ClassWidget   Container     ClassWidget       Container 

This is very important because it radically changes how the framework behaves when updating a widget. Here's a curated list of the differences:

  • Since ClassWidget is inserted into the widget tree, it gets associated with an Element and can, therefore, have a BuildContext and specify a Key. This leads to better performances overall, as ClassWidgets can update independently from other widgets.
  • ClassWidget can be hot-reloaded, functionWidget cannot. Since the framework doesn't see functionWidget, then when its code change, the framework doesn't know that it has anything to hot-reload.
  • With functionWidget you could end up with very weird bug if you ever wanted to use a different function after some updates. This happens because since the framework doesn't see the functionWidget, it might reuse some old widget state instead of creating a new one.
  • By using classes, each part of your layout is always used in the same way: Using constructor. This abstracts the implementation details. It's important because with functions if you ever wanted to change it to a StatefulWidget, it'd be a breaking change.

The conclusion should be pretty clear already:

Do not use functions to create widgets.


:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: