Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Why should I ever use stateless widgets instead of functional widgets? #19269

Closed
lukepighetti opened this issue Jul 11, 2018 · 63 comments
Closed
Labels
d: api docs Issues with https://api.flutter.dev/ d: stackoverflow Good question for Stack Overflow

Comments

@lukepighetti
Copy link

lukepighetti commented Jul 11, 2018

Dart 2 shorthand makes writing functional widgets super nice, especially for a React/Javascript heathen like myself.

Why should I ever use Stateless Widgets?

screen shot 2018-07-11 at 12 24 06 pm

@vinceramcesoliveros
Copy link

My simple answer would be.
It doesn't change its state, it only builds the widget. I'm not familiar with react native but I find Stateless widget very useful.
https://docs.flutter.io/flutter/widgets/StatelessWidget-class.html

@lukepighetti
Copy link
Author

lukepighetti commented Jul 11, 2018

Stateless Widget doesn't change its state either, right?

My best argument for using StatelessWidget is to create a widget that can be used to build tons of widgets that inherit its properties.

But this brings up another question. In react there are Functional components and Class based components. Functional components just build a component, like I have done with my functional widget above.

Class based components can be extended (iirc) and they have state.

So why would Flutter have a class based component for both Stateless and Stateful widgets? What benefit does this provide over Functional and Class based being the two methods of constructing widgets? (Where class based always has state)

Is a StatefulWidget more expensive to use than StatelessWidget?

@jonahwilliams
Copy link
Member

There is nothing wrong with functions, but Widgets can be const and can have keys. Those are both very important features

@xster xster added the d: stackoverflow Good question for Stack Overflow label Jul 11, 2018
@xster
Copy link
Member

xster commented Jul 11, 2018

You also don't have the associated Element with the function. i.e. how would you put a button that navigates in the function if you don't have the BuildContext.

@lukepighetti
Copy link
Author

That's a good point. What stops someone from passing context as an argument, though?

@xster
Copy link
Member

xster commented Jul 11, 2018

There's no Element associated with a function so you're passing in someone else's BuildContext. Then you have to manually make sure you get the right BuildContext. If you had:

class SomeWidget
  Widget build(BuildContext context) 
    a Navigator
      your function(context)

And your function tries to push onto that navigator, it'd fail or get the wrong one. Then you'd have to manually wrap your function in a Builder and you're more or less back to having a StatelessWidget.

@lukepighetti
Copy link
Author

lukepighetti commented Jul 12, 2018

So functional components for breaking down big trees but that's about it, it sounds like. Or fast prototyping.

@xster
Copy link
Member

xster commented Jul 12, 2018

Ya, the main difference is in how it links to the Element tree (in that functions don't get references to Elements themselves and won't get triggered to rebuild themselves via the Element tree).

Some other examples:

  • If your subtree depends on an InheritedWidget, a StatelessWidget will get surgically be marked to rebuild itself. If you used a function, the widget that gave the function its BuildContext will get rebuilt.
  • A function itself won't get called to rebuild during hot reload. Someone else will have to bring it along. If you just passed a function into runApp at the root of your application, nothing will be rebuilt during hot reload.

@xster xster added the d: api docs Issues with https://api.flutter.dev/ label Jul 12, 2018
@rrousselGit
Copy link
Contributor

rrousselGit commented Aug 4, 2018

A few other things :

  • Loose dart named and factory constructors
  • Loose refactoring options. Such as convert to stateful widget or Swap widget with child/parent

In the end your only gain is 2-3 lines of code. Lines which can be generated fairly easily with a code snippet.

For instance in vscode, just write stless and press tab.

ezgif com-crop 2

@rrousselGit
Copy link
Contributor

rrousselGit commented Aug 4, 2018

Oh and another one :

Widgets shouldn't have to care how other widgets are implemented. If you had to do new MyStatefulClass but then do myStatelessFunction() then it would be inconsistent

Which means that if you ever need to convert your stateless widget into a stateful or the opposite then it is a breaking change.

@atreeon
Copy link

atreeon commented Aug 5, 2018

Thanks for your input Rémi, it is much appreciated. It seems like there are a lot of very valid reasons indeed to use Stateless & Stateful and not use a 'functional widget'.

I think the breaking change issue is very significant and I think I'm mostly convinced to always use a Stateless or a Stateful widget.

However, I think the number of lines problem is significant, writing code using a code snipet is not the problem here, it is reading those lines back. Also, if the 'functional widget' requires one parameter we go from five lines of code to one line of code, this is really significant when looking back through code and trying to work out what my code does (83% fewer lines of code, 54 chars vs 169, 68% fewer chars, again this is significant when looking back through code).

Widget MyFunctionalWidget(String text) => Text(text);

class MyWidgetComposition extends StatelessWidget {
  final String text;
  MyWidgetComposition(this.text);

  Widget build(BuildContext context) => Text('hello');
}

Flipping the question a little bit more (by the way I do love Flutter have dropped React Native for it!), is it ever ok to use a 'functional widget'? As a starter I would say it is ok privately inside a stateless or stateful widget.

@rrousselGit
Copy link
Contributor

rrousselGit commented Aug 5, 2018

Well, if you really dislike the class syntax; it should be fairly straightforward to fix most of the previous downsides using a code generator

You could write the following :

// foo.dart
part 'foo.g.dart';


@stateless
Widget _MyStateless({String foo}) => Text(foo);

which then generates the following

// foo.g.dart
part of 'foo.dart';

class MyStateless extends StatelessWidget {
  final String foo;

  MyStateless({this.foo, Key key}): super(key: key);


  @override
  Widget build(BuildContext context) {
    return _MyStateless(foo: foo);
  }
}

That would be a much more reasonable approach to functional widgets.

The downside is that IDE shortcuts such as Jump to definition would land on the generated code. And you'd still break convert to stateful widget. But you could add a support for it in the IDE

Would that be fine with you?

@atreeon
Copy link

atreeon commented Aug 5, 2018

Thanks Remi, I'll have a play, that looks promising :-)

@lukepighetti
Copy link
Author

lukepighetti commented Aug 8, 2018

That would seem like a huge step in the right direction without going full JSX/DSX and is basically what I was trying to brainstorm in #19811

My current approach is to fit functional widgets only inside larger stateful/stateless class based widgets but even this isn't great for readability, and it makes my app nearly monolithic. If it never needs context or key, it stays functional, for example a _loading() => Center(child: CircularProgressIndicator()) widget should never be class based in my opinion, the boilerplate is not worth it.

The class format is really obtrusive in my opinion and if there is a way to reduce it without breaking anything else in an optional fashion would be ideal.

If I were writing a framework/package I would never use shorthand, but if I'm writing an app I am shorthand all the way.

This is a staple format for me

_title(String text) => Text(text, style: TextStyle(fontSize: 18.0));

I will NEVER

class _Title extends StatelessWidget {
  _Title(this.text);
  String text;

  @override
  Widget build(BuildContext context) {
    return Text(text, style: TextStyle(fontSize: 18.0),);
  }
}

If I could do this, I absolutely would, especially if it exposed context and key.

@stateless
_Title(String text) => Text(text, style: TextStyle(fontSize: 18.0));

And to be perfectly honest, I actually prefer that my widgets have a different syntax highlighting and style compared to built-in/pub widgets. It makes it so much easier to see what are widgets that I maintain, and what are widgets that someone else maintains.

@lukepighetti
Copy link
Author

@twistedinferno @rrousselGit did either of you get the @stateless / @stateful shorthand working? I would absolutely love to try it.

@rrousselGit
Copy link
Contributor

rrousselGit commented Aug 8, 2018

@stateful doesn't make sense.
But I can make a package for the @stateless.

@lukepighetti
Copy link
Author

lukepighetti commented Aug 8, 2018

Just out of curiosity, why do you say @stateful doesn't make sense? Just want to make sure I am understanding this fully.

And that would be fantastic and I would love to try it out and see what your solution is.

@rrousselGit
Copy link
Contributor

Sorry for the delay.
Here it is: https://github.com/rrousselGit/functional_widget

From

@widget
Widget foo(BuildContext context, { int value, int value2 }) {
  return Text('$value $value2');
}

it generates the following class for you to use:

class Foo extends StatelessWidget {
  final int value;
  final int value2;

  const Foo({Key key, this.value, this.value2}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return foo(context, value: value, value2: value2)
  }
}

@zoechi
Copy link
Contributor

zoechi commented Dec 13, 2018

I think this is solved and I'm going to close.
Please add a comment to have it reopened if you disagree.

@Maldus512
Copy link

Maldus512 commented Jan 14, 2019

There's no Element associated with a function so you're passing in someone else's BuildContext. Then you have to manually make sure you get the right BuildContext. If you had:

class SomeWidget
Widget build(BuildContext context)
a Navigator
your function(context)

And your function tries to push onto that navigator, it'd fail or get the wrong one. Then you'd have to manually wrap your function in a Builder and you're more or less back to having a StatelessWidget.

Could you elaborate further? I don't exactly understand either the principle or the pseudocode. I've tried pushing onto a navigator from a widget yielding function, using a BuildContext passed from the Widget, and it works as expected.

@rrousselGit
Copy link
Contributor

class Foo extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: home(context),
    );
  }
}

Widget home(BuildContext context) {
  return Scaffold(
    body: Center(
      child: RaisedButton(
        onPressed: () => Navigator.of(context).pushNamed('/foo'),
        child: Text('bar'),
      ),
    ),
  );
}

This won't work. Because home doesn't create a new context, it reuses an existing one; which has a different location.

To solve this issue, you'd have to write:

Widget home() {
  return Builder(
    builder: (context) => Scaffold(
          body: Center(
            child: RaisedButton(
              onPressed: () => Navigator.of(context).pushNamed('/foo'),
              child: Text('bar'),
            ),
          ),
        ),
  );
}

But that Builder kinda defeats the point of functions.

@lukepighetti
Copy link
Author

lukepighetti commented Jan 14, 2019

I believe @rrousselGit is describing an edge case where the context doesn't have a navigator. The problem isn't passing context to a functional widget, the problem is passing a context that is unaware of a MaterialApp.

This would only be a problem in practice if you don't have any builder methods between MaterialApp and your functional widget. (I have often wondered why home: isn't a builder)

@Maldus512
Copy link

So the problem only arises if the passed context was created before the MaterialApp, which is supposed to configure the top level Navigator, correct?
On the other hand a Widget will always have a correctly configured Navigator on creation.

@rrousselGit
Copy link
Contributor

A good sums up:

Classes:

  • have hot-reload
  • are integrated into the widget inspector (debugFillProperties)
  • rebuild less often by overriding operator==
  • can define keys
  • ensure all widgets are used in the same way
  • ensure that switching between two different layouts correctly disposes of the associated resources
  • can use the context API
  • can be const

Functions have:

@lukepighetti
Copy link
Author

@Maldus512 you got it.

@SaeedMasoumi
Copy link

Guys, I get confused.

Should I really avoid to do something like this?

return ListView(
  children: <Widget>[
    _buildMyStatelessWidget(), // a simple Text widget
    _buildMyStatelessWidget2(context), // a widget that reads some properties from context.theme
    _buildMyStatefulWidget(),
   ]
);

@whoiscarlo
Copy link

@SaeedMasoumi can you show the rest of the code for _buildMyStatelessWidget and _buildMyStatefulWidget

@SaeedMasoumi
Copy link

SaeedMasoumi commented Apr 3, 2019

@WantMoreCookies

_buildMyStatelessWidget() => ImageIcon(AssetImage("example.png"));
// or using const
_buildMyStatelessWidget() => const SizedBox(height: 20);

_buildMyStatelessWidget2(context) => Text(
      S.of(context).some_text,
      style: Theme.of(context).textTheme.title,
    );

_buildMyStatefulWidget() => MyScreen();

@whoiscarlo
Copy link

@SaeedMasoumi yea so this is exactly what you want to avoid doing. Instead you will want to do this:

class _Text extends StatelessWidget {
	const _Text(): super(key: key);

	Widget build(BuildContext context){
		return Text(
				S.of(context).some_text,
				style: Theme.of(context).textTheme.title,
			);

	}
}

class MainWidget extends StatelessWidget {
	const MainWidget(): super(key: key);

	Widget build(BuildContext context){
		return ListView(
			children: <Widget>[
				ImageIcon(
					AssetImage("example.png")
				),
				_Text,
				MyScreen(),
			]
		);
	}
}

@SaeedMasoumi
Copy link

SaeedMasoumi commented Apr 4, 2019

@WantMoreCookies I don't know what are the downsides of my approach and why I should use classes instead, I can even achieve hot reloading with functional widgets.

@sergiuiacob1
Copy link

sergiuiacob1 commented Apr 27, 2019

Could somebody answer @SaeedMasoumi 's last comment? I'm also wondering why it's a bad approach. It seems way too much to create a StatelessWidget just for a SizedBox

What if instead of the code above, the ListView were inside a StatelessWidget? Would it then be ok to use functions to build the "small parts" of the class?

class ListViewWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return ListView(children: <Widget>[
      _buildMyStatelessWidget(), // a simple Text widget
      _buildMyStatelessWidget2(
          context), // a widget that reads some properties from context.theme
      _buildMyStatefulWidget(),
    ]);
  }
}

like so

@whoiscarlo
Copy link

@SaeedMasoumi @sergiuiacob1 - This and this written by @rrousselGit should help you understand why.

tldr; "The framework [Flutter] is unaware of functions, but can see classes. Functions are not inserted in the Widget tree and therefore are never associated to an Element. This causes a whole new set of problems, including performance issues or state not properly disposed."

@SaeedMasoumi
Copy link

@WantMoreCookies

This causes a whole new set of problems, including performance issues or state not properly disposed.

Is there any example to show these performance issues?

For example, what are the performance issues of the below function?

SizedBox vGap4() => const SizedBox(height: 4);

Maybe @rrousselGit can help.

@rrousselGit
Copy link
Contributor

rrousselGit commented May 8, 2019

TD;DR: misused functions are a lot more dangerous than misused classes. So use classes


Honestly, the performance aspect barely matters.
The real deal-breaker is that using functions can have a very undesired behavior.

Consider:

bool condition;

Widget _foo();
Widget _bar();

Widget build(BuildContext context) {
  return condition
    ? _foo()
    : _bar();
}

With that code, flutter is unable to understand when we switch between _foo and _bar.
This can have heavy consequences that I described a bit in the previous links.

While classes require a bit more code, they are a lot safer.

@derolf
Copy link

derolf commented Aug 17, 2019

I know I am coming late to the party. But, that question always pops up again. I think an important aspect is that Flutter stops rebuilding if encounters an equal widget at the same position in the tree.

Hence, by overriding operator== in a stateless widget you can make Flutter stop rebuilding. That's impossible with functions. Flutter will always "expand" them.

The Flutter docs read "same instance", but in reality they mean "equal instance". So, I opened a ticket to ask the Flutter team to clarify and emphasize that in the docs: #38740

@lukepighetti
Copy link
Author

I have often wished for a shouldRebuild() method a la react, but it sounds like overriding operator gets something similar?

@ishammahajan
Copy link

While classes require a bit more code, they are a lot safer.

@rrousselGit Would you please provide equivalent code for the Class paradigm? I thought I had this concept cleared up until reading that last comment 😓

@Maldus512
Copy link

Maldus512 commented Nov 22, 2019

TD;DR: misused functions are a lot more dangerous than misused classes. So use classes

Honestly, the performance aspect barely matters.
The real deal-breaker is that using functions can have a very undesired behavior.

Consider:

bool condition;

Widget _foo();
Widget _bar();

Widget build(BuildContext context) {
  return condition
    ? _foo()
    : _bar();
}

With that code, flutter is unable to understand when we switch between _foo and _bar.
This can have heavy consequences that I described a bit in the previous links.

While classes require a bit more code, they are a lot safer.

I'm not sure this is the case. Wouldn't the same problem apply to classes as well? If that build function is used as the build method of any Widget Flutter will face the same uncertainty... The problem here is with dynamic behavior in general, and neither classes nor functions can fix that.

@derolf
Copy link

derolf commented Nov 22, 2019

Classes will dispose the element and state when they are switched.

With functions, it might happen that state leaks between succeeding trees. A password might suddenly appear somewhere else as readable text.

@hmayer00
Copy link

hmayer00 commented Dec 8, 2019

So is there any difference between using a function that returns a Widget and just inlining the Widget? For (a very contrived) example:

class Toggler extends StatelessWidget {
  final VoidCallback onToggle;
  final VoidCallback onAdvancedToggle;
  const Toggler({Key key, this.onToggle, this.onAdvancedToggle}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Row(
      children: <Widget>[
        FlatButton(onPressed: onToggle, onLongPress: onAdvancedToggle, child: Text('On')),
        FlatButton(onPressed: onToggle, onLongPress: onAdvancedToggle, child: Text('Off')),
      ],
    );
  }
}

Here I'm using a couple of member variables while building the FlatButton, and it looks like a candidate for DRYing up. However making it a stateless widget doesn't help at all, since then I still lose the member variables and just have to pass the same values. So my instinct is:

  //...

  Widget _toggleButton(String text) =>
        FlatButton(onPressed: onToggle, onLongPress: onAdvancedToggle, child: Text(text));

  @override
  Widget build(BuildContext context) {
    return Row(
      children: <Widget>[
        _toggleButton('On'),
        _toggleButton('Off'),
      ],
    );
  }

Is that bad? For at least some of the points made elsewhere, I think that using a function that returns a Widget should be the same as inlining code? But then again @rrousselGit's comment that

The real deal-breaker is that using functions can have a very undesired behavior.

makes me question whether I actually understand it. So I get that there are important differences between extracting a StatelessWidget and using a function. But is using a function different from inlining the code directly in the build method?

@derolf
Copy link

derolf commented Dec 8, 2019

@hmayer00 inlining and using a function is exactly the same.

The difference is between inlining/function and a proper widget-class.

In the first case, Flutter aggressively tries to reuse the elements and state. In the, second case Flutter will only reuse the element and state iff the runtimeType and the key match.

Consider two forms with text edits at the same location in the widget tree and switching between the forms. Do you want the edited text to spill over from the first to the second form or reset when you switch between the forms? The first is achieved with inlining/function, the later with proper subclasses or different keys.

@rrousselGit
Copy link
Contributor

rrousselGit commented Dec 8, 2019

@derolf is on point.

If that wasn't clear enough, here's a concrete example:

Widget functionA() => Container()

@override
Widget build() {
  return functionA()  
}

is equivalent to:

@override
Widget build() {
  return Container();  
}

whereas:

class ClassA extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container();  
  }
}

@override
Widget build() {
  return ClassA()  
}

is equivalent to:

@override
Widget build() {
  return KeyedSubtree(
    key: ObjectKey(ClassA),
    child: Container(),
  );
}

@derolf
Copy link

derolf commented Dec 8, 2019

Btw https://flutter.dev/docs/development/ui/widgets-intro#keys explains it all...

@hmayer00
Copy link

hmayer00 commented Dec 9, 2019

Thanks @derolf and @rrousselGit. That's what I had thought, but things seemed tricky enough that I wanted to make sure I hadn't missed something. And you and others have in previous comments certainly convinced me of the value of widget classes (also it helps that functional_widget_annotation takes away some of the boilerplate when convenient - thanks @rrousselGit!).

Btw, to @derolf's point about keys, I'm generally averse to learning by video, but I found the intro video about keys to be extremely helpful.

@derolf
Copy link

derolf commented Dec 9, 2019

@hmayer00 To understand how Flutter works, it's quite helpful to:

  • Always consider that Flutter doesn't contain any black magic. It follows clear rules (like the frame-by-frame widget matching).
  • Even if you don't need to write your own RenderObjects, just write some out of curiosity. That way you learn a lot about Flutter's rendering pipeline.

@rrousselGit
Copy link
Contributor

rrousselGit commented Dec 9, 2019

For those who don't want to use code-generators/functional_widget, there are other alternatives.

We can use "higher order functions".

TD;DR instead of:

Widget myWidget(String title) {
  return Text(title);
}

Builder(
  key: ValueKey(42),
  builder: (context) {
    return myWidget('hello world');
  },
)

you do:

final myWidget = functionalWidget((BuildContext context, String title) {
  return Text(title);
});

myWidget('hello world', key: ValueKey(42));

Here's the functionalWidget function's source code:

Widget Function(T props, {Key key}) functionalWidget<T>(
    Widget value(BuildContext c, T props)) {
  final uniqueWidgetIdentifier = UniqueKey();
  return (props, {Key key}) {
    var child = Builder(
      key: uniqueWidgetIdentifier,
      builder: (context) {
        return value(context, props);
      },
    );
    if (key != null) {
      return KeyedSubtree(
        key: key,
        child: child,
      );
    }
    return child;
  };
}

The downside is, if the props of your function are anything more complex than a String, you have to write a class for them:

class MyProps {
  String title;
  int count;
}

final myComplexWidget = functionalWidget<MyProps>((context, props) {
  return Text('${props.title} ${props.count}');
});

myComplexWidget(
  MyProps()
    ..title = 'Hello world'
    ..count = 42,
)

It'd be perfect if Dart had structures/records though.

@erperejildo
Copy link

I just use on my app Stateless widgets. What I use is a global provider that I share within my pages.
This provider updates the UI if it's needed. For example, if I want to change some UI values I do something like this from my Stateless widget:
Provider.of<Game>(context).addTeams();
and inside my provider I have this:

class Game extends ChangeNotifier {
  List teams = [];
  String something = '';

  addTeams() {
    Map newTeam = {
       name: 'New Team'
    }
   this.teams.add(newTeam);
   // and now this is the trick. I if need to update the UI I call this method
   notifyListeners();
  }
}

I find the Stateful widget not too easy to use/understand so I prefer to have something like this.

There are some specific scenarios that require me to update the UI without modifying the global provider. For this I just use StateFulBuilder: https://api.flutter.dev/flutter/widgets/StatefulBuilder-class.html

@mazei513
Copy link

Am I understanding it right if I say

  @override
  Widget build(BuildContext context) {
    return Container(
      color: Colors.red,
      child: const Text('Hello world', style: TextStyle(color: Colors.blue)),
    );
  }

Can be refactored as

  @override
  Widget build(BuildContext context) {
    return Container(
      color: Colors.red,
      child: const _MyText(),
    );
  }
// ...
class _MyText extends StatelessWidget {
  const _MyText({Key key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return const Text('Hello world', style: TextStyle(color: Colors.blue));
  }
}

And never as

  @override
  Widget build(BuildContext context) {
    return Container(
      color: Colors.red,
      child: _buildMyText(),
    );
  }

  Widget _buildMyText() {
    return const Text('Hello world', style: TextStyle(color: Colors.blue));
  }

And it is fine for

  final List<Fruit> fruits;
//...
  @override
  Widget build(BuildContext context) {
    return Column(
      children: fruits.map((f) => _FruitInfo(fruit: f)).toList(),
    );
  }

to be refactored to

  final List<Fruit> fruits;
//...
  @override
  Widget build(BuildContext context) {
    return Column(
      children: _buildChildren(),
    );
  }

  List<Widget> _buildChildren() {
    return fruits.map((f) => _FruitInfo(fruit: f)).toList();
  }

and it is fine because the inline and function implementations are no different. Or is there another way to build a List<Widget> that I don't know of.

@erperejildo
Copy link

why a normal widget without class is wrong? I think it depends if you need a different context

@derolf
Copy link

derolf commented Jan 24, 2020

There is no hard rule. It’s just best practices! The reasons were already given multiple times in this thread.

@derolf
Copy link

derolf commented Jan 24, 2020

Here is the hard and fast logic again:

@hmayer00 inlining and using a function is exactly the same.

The difference is between inlining/function and a proper widget-class.

In the first case, Flutter aggressively tries to reuse the elements and state. In the, second case Flutter will only reuse the element and state iff the runtimeType and the key match.

Consider two forms with text edits at the same location in the widget tree and switching between the forms. Do you want the edited text to spill over from the first to the second form or reset when you switch between the forms? The first is achieved with inlining/function, the later with proper subclasses or different keys.

@DrSensor
Copy link

Wish primary constructor landed on dart dart-lang/language#138 so I don't need to use functional widget to reduce LoC.

@rimidalv
Copy link

Here is the hard and fast logic again:

@hmayer00 inlining and using a function is exactly the same.
The difference is between inlining/function and a proper widget-class.
In the first case, Flutter aggressively tries to reuse the elements and state. In the, second case Flutter will only reuse the element and state iff the runtimeType and the key match.

I read whole topic and I can't understand WHY?! Why Flutter aggressively tries to reuse the elements and state?
Could somebody correct me:
if I write a function, for example:

Widget functionA() => Container()

And assign it to constructor parameter.
the first would created widget "Container() and then this Container would insert in widget Center and then inside widget Scaffold (for example):

Widget home(BuildContext context) {
  return Scaffold(
    body: Center(
         child: functionA(),
    ),
  );
}

The first of all compiler initialise all objects and executes all methods/functions and create all widgets and after that Flutter will check elements and states. Then will make a decision to reuse element and render objects.

And I think the same will be when I use StatelessWidget.

But you say NO. Not the same. Could you describe step by step what difference? May be Flutter start check runtimeType and the key in different order? But how?!

@lock
Copy link

lock bot commented Apr 5, 2020

This thread has been automatically locked since there has not been any recent activity after it was closed. If you are still experiencing a similar issue, please open a new bug, including the output of flutter doctor -v and a minimal reproduction of the issue.

@lock lock bot locked and limited conversation to collaborators Apr 5, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
d: api docs Issues with https://api.flutter.dev/ d: stackoverflow Good question for Stack Overflow
Projects
None yet
Development

No branches or pull requests