0
votes

I was always wondering, why I have to "lift the state up" of some widget down in the tree, to reflect changes in the widget's UI.. Can't I just simply have multiple stateful Widgets? and for example, import the lowest stateful widget down the tree into my top-level Widget, and from there could I not just call some method of my widget which triggers its setState() method and just updates that part in the DOM tree that is concerned with my widget?

And secondly, I would then have to move my properties and other important parts from the lower widget also up into my higher state widget, risking to clutter that class with unrelated functions and properties at some time, in my opinion, React solves that way better by just passing method callbacks down as it suits...

And is there always only one stateful widget in my Flutter app at the highest level?

2
That's the reason why there are so many variations of state management solution in Flutter.Federick Jonathan
do you trying to make multiple statefulwidget that have their own state, and you want the callback from every widget?Gilang Pratama

2 Answers

1
votes
  • Parents don't have access to child widgets/states, only the other way around. So you can not "import the lowest stateful widget down the tree into my top-level Widget"

  • You only have to "lift the state up" when you want to share that state between different branches of the widget tree. Then the children can lookup the parent and access the shared state.

  • Don't be afraid of StatefulWidget - you can use as many as you need

  • Research Flutter state management solutions which exist exactly for the purpose of keeping things separated (ChangeNotifier, Provider, BLOC, Redux, etc.)

0
votes

Can I have multiple widgets with state in my Widgets tree?

The answer is, yes you can create multiple StatefulWidget in your widget. You can also create a callback function from the lowest StatefulWidget with Function(yourcallback). In my opinion, flutter also support component base model, and make as dynamic as possible to customize our own widget.

For example:

child widget

child widget has it's state.

class Child extends StatefulWidget {
  final int counter;
  final Function(int childCounter) callback; //here is your callback
  const Child({
    Key key,
    this.counter,
    this.callback,
  }) : super(key: key);
  @override
  _ChildState createState() => _ChildState();
}

class _ChildState extends State<Child> {
  String _childState = '';

  @override
  Widget build(BuildContext context) {
    return Container(
      color: Colors.green[400],
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.center,
        children: [
          Text("Child"),
          Row(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              IconButton(
                  icon: Icon(Icons.exposure_minus_1_rounded),
                  onPressed: () {
                    this.widget.callback(this.widget.counter - 1); //here is your callback
                    setState(() {
                      _childState = "minus one";
                    });
                  }),
              IconButton(
                  icon: Icon(Icons.plus_one_rounded),
                  onPressed: () {
                    this.widget.callback(this.widget.counter + 1); //here is your callback
                    setState(() {
                      _childState = "plus one";
                    });
                  })
            ],
          ),
          Text(_childState)
        ],
      ),
    );
  }
}

Parent Widget

the parent get the callback from the child.

class Parent extends StatefulWidget {
  @override
  _ParentState createState() => _ParentState();
}

class _ParentState extends State<Parent> {
  int _counter = 0;
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Multiple State"),
      ),
      body: Container(
        child: Column(
          children: [
            Child(
              counter: _counter,
              callback: (childCounter) { //here is callback from the child
                print(childCounter);
                setState(() {
                  _counter = childCounter;
                });
              },
            ),
            Text("Parent"),
            Center(
              child: Text(_counter.toString()),
            )
          ],
        ),
      ),
    );
  }
}

to change the child state from it's parent

you can use didUpdateWidget() here you can see the docs