Rendering duplicate widgets
hamsbrar opened this issue · comments
If widgets are able to call build/update on the parent context while that context is already under build then it can lead to some inconsistencies in the generated markup.
For example, calling setState()
synchronously during build can generate duplicate widgets. Below is the test case in which setState
is getting called synchronously during a Navigator
widget build as Navigator
fires its hooks(e.g onInit
) while building:
class NavigatorTest extends StatefulWidget {
const NavigatorTest({String? key}) : super(key: key);
@override
_NavigatorTestState createState() => _NavigatorTestState();
}
class _NavigatorTestState extends State<NavigatorTest> {
@override
build(context) {
return Division(
children: [
navigatorContent(),
Text('|more text'),
],
);
}
Widget navigatorContent() {
return Navigator(
onInit: (state) => setState(() {}),
onRouteChange: (name) => setState(() {}),
routes: [
Route(name: 'some', page: Text('|some text on route')),
],
);
}
}
Expected output on screen:
|some text on route|more text
Actual output on screen:
|some text on route|more text|more text
Quick fix: Delaying the setState
call in such cases can prevent framework from rendering duplicate widgets
Future.delayed(Duration.zero, () {
setState(() { });
});
Note this is a temporary fix so thought I should document it in case anyone came across this issue. I'm going to work on some sort of scheduler to make sure this never happens again.