43

I develop my own custom widget which is used in some other view. In this custom widget, I have one class property which stores information, let's say that this is a list which gains new items inside the widget. Now I want to get items from this list from the level of my main widget.

How to do that? I don't want to create a variable like this: var customWidget = MyCustomWidget() and then, get the inside variable like customWidget.createState().myList - I think this is a terrible solution (and I'm not sure if it will work). Also passing a list to the constructor of my custom widget looks very ugly.

Is there any other way to get other widget's state?

Rémi Rousselet
  • 256,336
  • 79
  • 519
  • 432
mynameis
  • 777
  • 3
  • 10
  • 18
  • 2
    Also have a look at these sites for architecture examples/ideas https://medium.com/@maksimrv/reactive-app-state-in-flutter-73f829bcf6a7 https://github.com/brianegan/flutter_architecture_samples – Rene Feb 22 '18 at 09:15
  • Hi, Did not understand how you solved it in real, can you help me with this one: https://stackoverflow.com/questions/49824461/how-to-pass-data-from-child-widget-to-its-parent – Hasan A Yousef Apr 13 '18 at 20:23
  • suggestion: instead of posting an update to your question, you can post an answer to your own question, so this question won't appear in the 'unanswered questions' – Feu Aug 31 '18 at 13:28
  • Highly recommend Flutter's official documentation on state management: https://docs.flutter.dev/development/data-and-backend/state-mgmt/options This is a list of your possible options and relevant use cases. If you go up one section, they have a great walkthrough on state management in general – Oded Ben Dov Nov 02 '22 at 11:55

2 Answers2

41

First, bear in mind that in Flutter data can only be passed downward. It is by design not possible to access data of children, only parents (although there are some hacks around it).

From this point, there are 2 main solutions to pass data:

  1. Add the wanted data to your widgets constructors.

I don't think there is much to say here. Easy to use. But boring when you want to pass one field to all your widget tree. Use this method only when the scope of a value is limited. If it's something like configurations or user details, go for the second solution.

class Bar extends StatelessWidget {
  final String data;

  Bar({this.data});

  @override
  Widget build(BuildContext context) {
    return Text(data);
  }
}
  1. Using Flutter's BuildContext

Each widget has access to a BuildContext. This class allows one widget to fetch information from any of their ancestors using one of the following methods:

As a matter of facts, if there's a data that needs to be accessed many times, prefer inheritFromWidgetOfExactType.

This uses InheritedWidget; which are specifics kind of widgets that are extremely fast to access to.

See Flutter: How to correctly use an Inherited Widget? for more details on their usage


As a side note, there a third solution. Which is GlobalKey

I won't go into too many details, as this is more a hack than a proper solution. (see Builder versus GlobalKey)

But basically, it allows getting the state/context of any widgets outside of the build call. Be it parents or children.

Rémi Rousselet
  • 256,336
  • 79
  • 519
  • 432
1

on my side I implemented onChanged callback.

For example In my Widget :

class ObjectiveCardWidget extends StatefulWidget {
  final Objective? objective;
  final ValueChanged<Objective?>? onChanged;
  ObjectiveCardWidget({this.objective, this.onChanged});
  @override
  State<ObjectiveCardWidget> createState() => _ObjectiveCardWidgetState();
}

when my data is updated un my custom widget I just called :

widget.onChanged!(newValue);  // newvalue has been set previously

In my parentWidget I used onChanged as usual:

ObjectiveCardWidget(
              objective: myObjective,
              onChanged: (value) {
                setState(() {
                  myObjective = value;
                });
              })

Hope it will help.

Saeba
  • 11
  • 3