erlage / rad

A zero-dependency web framework for creating high-performant web apps using Dart.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

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.