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

Stepper doesn't let's childs update their state ? #22033

Closed
Nik99 opened this issue Sep 19, 2018 · 14 comments
Closed

Stepper doesn't let's childs update their state ? #22033

Nik99 opened this issue Sep 19, 2018 · 14 comments

Comments

@Nik99
Copy link

Nik99 commented Sep 19, 2018

Hi everyone.
I'm trying to make a stepper with star rating inside every step, but while the values changes, the UI does not. It seems like it's not refreshing the content.

The plugin for rating is this: https://pub.dartlang.org/packages/flutter_rating

This is my test code:

double rating = 0.0;

List<Step> questions = [
      Step(
          content: StarRating(
              rating: rating,
              color: Colors.orange,
              borderColor: Colors.grey,
              size: 50.0,
              starCount: 5,
              onRatingChanged: (rating) => setState(() {
                    this.rating = rating;
                  })),
          title: Text('XX')),
     ]

If i take it outside of the stepper, it works and refreshes it self nicely.

@Nik99 Nik99 changed the title Stepper doesn't let's child update their state ? Stepper doesn't let's childs update their state ? Sep 19, 2018
@zoechi
Copy link
Contributor

zoechi commented Sep 24, 2018

Is this in a stateful or statless widget.
Please post a fully runnable but minimal example.

Please also add the output of flutter doctor -v.

@zoechi zoechi added the waiting for customer response The Flutter team cannot make further progress on this issue until the original reporter responds label Sep 24, 2018
@Nik99
Copy link
Author

Nik99 commented Sep 25, 2018

This is in a stateful widget. Because the method setState was working, and in the variable it was updating the value, but the UI would stay at the beginning state, not letting StarRating to refresh itself.

class Demo extends StatefulWidget {
  @override
  _DemoState createState() => _DemoState();
}

class _DemoState extends State<Demo> {

  int current_step = 0;
  double rating = 0.0;
  double rating2 = 0.0;

  List<Step> questions = [
    Step(
        content: StarRating(
            rating: rating,
            color: Colors.orange,
            borderColor: Colors.grey,
            size: 50.0,
            starCount: 5,
            onRatingChanged: (rating) =>
                setState(() {
                  this.rating = rating;
                })),
        title: Text('XX')),
    Step(
        content: StarRating(
            rating: rating2,
            color: Colors.orange,
            borderColor: Colors.grey,
            size: 50.0,
            starCount: 5,
            onRatingChanged: (rating) =>
                setState(() {
                  this.rating2 = rating;
                })),
        title: Text('XX2')),
  ];

  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      // Appbar
      appBar: new AppBar(
        // Title
        title: new Text("Simple Material App"),
      ),
      // Body
      body: new Container(
          child: new Stepper(
            // Using a variable here for handling the currentStep
            currentStep: this.current_step,
            // List the steps you would like to have
            steps: questions,
            // Define the type of Stepper style
            // StepperType.horizontal :  Horizontal Style
            // StepperType.vertical   :  Vertical Style
            type: StepperType.vertical,
            // Know the step that is tapped
            onStepTapped: (step) {
              // On hitting step itself, change the state and jump to that step
              setState(() {
                // update the variable handling the current step value
                // jump to the tapped step
                current_step = step;
              });
              // Log function call
              print("onStepTapped : " + step.toString());
            },
            onStepCancel: () {
              // On hitting cancel button, change the state
              setState(() {
                // update the variable handling the current step value
                // going back one step i.e subtracting 1, until its 0
                if (current_step > 0) {
                  current_step = current_step - 1;
                } else {
                  current_step = 0;
                }
              });
              // Log function call
              print("onStepCancel : " + current_step.toString());
            },
            // On hitting continue button, change the state
            onStepContinue: () {
              setState(() {
                // update the variable handling the current step value
                // going back one step i.e adding 1, until its the length of the step
                if (current_step < my_steps.length - 1) {
                  current_step = current_step + 1;
                } else {
                  current_step = 0;
                }
              });
              // Log function call
              print("onStepContinue : " + current_step.toString());
            },
          )),
    );
  }
}
[✓] Flutter (Channel dev, v0.9.2, on Mac OS X 10.13.6 17G65, locale it-IT)
    • Flutter version 0.9.2 at /Users/me/flutter
    • Framework revision 85b4670b2a (5 days ago), 2018-09-19 14:59:23 -0700
    • Engine revision 2e8e96fad1
    • Dart version 2.1.0-dev.4.0.flutter-4eb879133a

[✓] Android toolchain - develop for Android devices (Android SDK 28.0.2)
    • Android SDK at /Users/me/Library/Android/sdk
    • Android NDK location not configured (optional; useful for native profiling support)
    • Platform android-28, build-tools 28.0.2
    • Java binary at: /Applications/Android Studio.app/Contents/jre/jdk/Contents/Home/bin/java
    • Java version OpenJDK Runtime Environment (build 1.8.0_152-release-1024-b01)
    • All Android licenses accepted.

[✓] iOS toolchain - develop for iOS devices (Xcode 10.0)
    • Xcode at /Applications/Xcode.app/Contents/Developer
    • Xcode 10.0, Build version 10A255
    • ios-deploy 1.9.2
    • CocoaPods version 1.5.3

[✓] Android Studio (version 3.1)
    • Android Studio at /Applications/Android Studio.app/Contents
    • Flutter plugin version 28.0.1
    • Dart plugin version 173.4700
    • Java version OpenJDK Runtime Environment (build 1.8.0_152-release-1024-b01)

[✓] VS Code (version 1.27.1)
    • VS Code at /Applications/Visual Studio Code.app/Contents
    • Flutter extension version 2.18.0

[✓] Connected devices (2 available)

@no-response no-response bot removed the waiting for customer response The Flutter team cannot make further progress on this issue until the original reporter responds label Sep 25, 2018
@zoechi
Copy link
Contributor

zoechi commented Sep 25, 2018

That's because

List<Step> questions = [

makes StarRating(...) be built only once and then the same instance is reused every time.

Changing it to

List<Step> get questions => [

should fix that already.

@zoechi zoechi closed this as completed Sep 25, 2018
@zoechi
Copy link
Contributor

zoechi commented Sep 25, 2018

Ups, didn't mean to close, but I think the question is answered anyway.
Feel free to add more comments anyway.

Please consider asking support questions in one of the other channels listed at http://flutter.io/support .

@Nik99
Copy link
Author

Nik99 commented Sep 25, 2018

What's the difference between using a get and not using it ? never understood it.
Thanks by the way :)

@zoechi
Copy link
Contributor

zoechi commented Sep 25, 2018

The difference is that with a getter the code after => is evaluated every time the getter is accessed, while the code after = is only evaluated once when the class' instance is created.

@Nik99
Copy link
Author

Nik99 commented Sep 25, 2018

Thanks. I've tryed with your method, but it doesn't work. If i put a setState inside the step content, it wont refresh the UI.

@zoechi
Copy link
Contributor

zoechi commented Sep 25, 2018

@Nik99
Copy link
Author

Nik99 commented Sep 25, 2018

Oh, ok. So apparently my problem is when i try to make it dynamic. Do you know a method on how to make the list of steps dynamic ?

@zoechi
Copy link
Contributor

zoechi commented Sep 25, 2018

Not sure what you mean.
Runnable code that allows to reproduce the issue would make this conversation much easier.

So it seems the whole question reduces to my_steps, the part that was missing in your reproduction and I had to add by making assumptions to get rid of the compilation error 😄

@Nik99
Copy link
Author

Nik99 commented Sep 25, 2018

Actually my problem is this.

So when the widget starts, i do have to make the list based on a series of widgets.

https://gist.github.com/Nik99/5c65b0751e3948d5ec894791cd254e7c

This is my code. As you can see, on the initState i compile the variable "domandeList" which is then used by get domande and after by the stepper. I think the problem stays here. I do have needs to dynamically generate the UI, but i also need to update the stepper. In your code, data is directly inserted in the initialization of the questions variable. Mine, is added after.
How can i solve this ?
I hope you understand me! :)

@Nik99
Copy link
Author

Nik99 commented Sep 25, 2018

The setState inside "inserisciRating" works, because i do see the prints on my console, but it just doesn't update the UI.

@zoechi
Copy link
Contributor

zoechi commented Sep 25, 2018

If you added the getter here because of my suggestion above, then this won't have an effect here because after => there is no computation going on. Here using a getter or adding the values directly doesn't make a difference because now you have to computation in initState() which also ensures that it is only executed once.

 get domande => domandeList;

  get getValutazioni => valutazioni;

You should just move

    votazioneMassima = widget.mappaDatiCustomer['elenco_valutazioni'].length;

    for (var domanda in widget.mappaDatiCustomer['elenco_domande']) {
      voti[domanda['id']] = 0;
      valutazioni[domanda['id']] = 0.0;

      domandeList.add(Step(
          title: Text(domanda['domanda']),
          content: Column(children: [
            Text(valutazioni[domanda['id']].toString()),
            inserisciRating(domanda['id'])
          ]),
          isActive: true));
    }

to build() so that it is executed every time build() is run (which is run after setState()).

Widgets with dynamic content need to be build in build().

@github-actions
Copy link

github-actions bot commented Sep 1, 2021

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.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Sep 1, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants