Reputation: 22518
I have a first screen which ask the user to enter to input, then when the users clicks on a button, the app goes on a second screen which uses a FutureBuilder to call an API.
If the API returns an error, I would like to go back to the previous screen with Navigator.pop. When I try to do that in the builder of the FutureBuilder, I get an error because I modify the tree while I am building it...
setState() or markNeedsBuild() called during build. This Overlay widget cannot be marked as needing to build because the framework is already in the process of building widgets
What is the proper way to go to the previous screen if an error occur?
class Stackoverflow extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: FutureBuilder<Flight>(
future: fetchData(context),
builder: (context, snapshot) {
if (snapshot.hasData) {
return ScreenBody(snapshot.data);
} else if (snapshot.hasError) {
Navigator.pop(context, "an error");
}
// By default, show a loading spinner.
return CircularProgressIndicator();
},
)
),
);
}
}
PS: I tried to use addPostFrameCallback and use the Navigator.pop inside, but for some unknown reason, it is called multiple times
Upvotes: 2
Views: 6566
Reputation:
I'd prefer to convert class into StateFullWidget
and get rid of FutureBuilder
class Stackoverflow extends StatefulWidget {
@override
_StackoverflowState createState() => _StackoverflowState();
}
class _StackoverflowState extends State<Stackoverflow> {
Flight flight;
@override
void initState() {
super.initState();
fetchData().then((data) {
setState(() {
flight = data;
});
}).catchError((e) {
Navigator.pop(context, "an error");
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: flight != null ? ScreenBody(flight) : CircularProgressIndicator(),
),
);
}
}
and of cause pass context
somewhere outside class is not good approach
Upvotes: 2
Reputation: 27137
You can not directly navigate when build method is running, so it better to show some error screen and give use chance to go back to last screen.
However if you want to do so then you can use following statement to do so.
Future.microtask(() => Navigator.pop(context));
Upvotes: 8