Why does a child state of StatefulWidget doesn't get reset when constructor parameter changes?

338

You State class will be able to listen to state changes in your StatefulWidget class if you use the widget property to access the state.

You'd need to change:

enabled ? Colors.red : Colors.green

to

widget.enabled ? Colors.red : Colors.green

Hope it helps.

Share:
338
Gintas_
Author by

Gintas_

Updated on December 20, 2022

Comments

  • Gintas_
    Gintas_ over 1 year

    I have a custom widget class:

    class FancyButton extends StatefulWidget
    {
      final Function() onTap;
      final String text;
      final IconData icon;
      bool enabled;
    
      FancyButton({this.onTap, this.text, this.icon, this.enabled = true})
    
      @override
      _FancyButtonState createState()
      {
        return _FancyButtonState(onTap, text, icon, enabled);
      }
    }
    
    class _FancyButtonState extends State<FancyButton> with SingleTickerProviderStateMixin
    {
      Function() onTap;
      String text;
      IconData icon;
      bool enabled;
      _FancyButtonState(this.onTap, this.text, this.icon, this.enabled);
    
      @override
      Widget build(BuildContext context) {
        if(!enabled)
          {
            print("build disabled");
          }
        return GestureDetector(
          onTap: onTap,
          child: Container(
              color: enabled ? Colors.red : Colors.green,
              height: 20
          ),
        );
      }
    }
    

    I'm using it like this:

    Widget continueButton = new StreamBuilder(
              stream: viewModel.canFinishProfile.asBroadcastStream(),
              initialData: viewModel.canFinishProfile.value,
              builder: (builder, snapshot)
              {
                print("can finish profile " + viewModel.canFinishProfile.value.toString());
                return FancyButton(
                  text: multilang.get("auth_continue"),
                  enabled: viewModel.canFinishProfile.value,
                  onTap: ()
                  {
                    viewModel.onClickedContinue.add(null);
                  },
                );
              },
            )
    

    So I'm expecting the widget to update once canFinishProfile value changes. The problem is that the FancyButton's state doesn't get updated once the canFinishProfile value changes, so an old widget view is always drawn. Note that if I change the FancyButton to be a StatelessWidget and put it's build code inside the StatelessWidget, then it redraws fine once then canFinishProfile value change. However, I need it to be a StatefulWidget for a more complex feature.

    • scottstoll2017
      scottstoll2017 about 4 years
      To start with, you can simplify this by getting rid of onTap, text, icon and enabled in your State object and then anytime you need to access them in the State, just use widget.onTap, widget.text, etc. What this does is tell the State to go get its parent's value for these things, so you don't have to pass them in. See what happens after that, then if you still have an issue check back in.
  • Gintas_
    Gintas_ about 4 years
    that's pretty interesting, I always used to copy the constructor params to the state. It worked! thanks a lot