Flutter reset StatefulWidget state when Widget is recreated
Asked Answered
A

2

7

In my Flutter Widget I have a StreamBuilder that checks for snapshot.hasError and in this specific case it will return my ErrorRetryWidget().

builder: (context, AsyncSnapshot<MyObject> snapshot) {
...
    if (snapshot.hasError) {
        return ErrorRetryWidget();
    }
}

The ErrorRetryWidget() just shows an error message and a retry button. When you press this button, I replace the button text by a progress indicator. Therefore I needed to make this widget stateful, as its state holds a isRetrying variable that I set to false in the initState, and then to true once pressed.

When pressing the button, the ErrorRetryWidget tells the parent through a VoidCallback to re-trigger the stream logic. It works well but the issue is that if the error comes back, my StreamBuilder will "return" the ErrorRetryWidget once again.

The constructor is called a new time, but not initState. How can I make it so the state resets every time the widget is re-created? Therefore, isRetrying is already (or still) set to true.

The only quick solution I found was to implement this in my error widget:

@override
void didUpdateWidget(covariant oldWidget) {
    super.didUpdateWidget(oldWidget);
    setState(() {
        retrying = false;
    });
  }

Not sure it's a good practice.

Athome answered 11/6, 2020 at 20:25 Comment(0)
T
10

Pass a unique key to let it create a new widget.

if (snapshot.hasError) {
    return ErrorRetryWidget(key: UniqueKey());
}
Tenebrous answered 11/6, 2020 at 21:27 Comment(0)
M
4

I use didUpdateWidget just as you said, to reset the state of a stateful widget. It is also useful in animations.

The only comment I would add is to NOT use setState as you did because when the framework calls didUpdateWidget, it immediately calls build. Therefore, you don't have to trigger a call to build within didUpdateWidget. It ends up calling build two times.

@override
void didUpdateWidget(covariant oldWidget) {
    super.didUpdateWidget(oldWidget);
    retrying = false;
  }
Mary answered 19/2, 2021 at 21:20 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.