Anti-patterns to Avoid

Most regressions occur when imperative and declarative navigation are mixed. Keep exactly one owner for each stack's state.

Mixing push/pop and pages

Do not call Navigator.push/pop on a stack already controlled by List<PageEntry>. Choose one navigation model for each stack.

Widgets in state

Do not put Widget instances in page metadata. Keep only keys and route-like identifiers. Rebuild the widget tree from declarative state.

Duplicate keys

Do not reuse PageEntry.key values within the same stack. Unique keys let the framework distinguish pages correctly.

Migration Checklist

Use this checklist during refactor reviews to keep the navigation architecture consistent. Check every path that can mutate a stack before approving the refactor.

Checklist

Good vs Bad

// Bad: mixing imperative and declarative for same stack
Navigator.of(context).push(...);
_pages = [..._pages, const PageEntry(key: 'detail', name: '/detail')];

// Good: update only declarative state
setState(() {
  _pages = [..._pages, const PageEntry(key: 'detail', name: '/detail')];
});
Review Tip

During code review, identify who owns stack mutations before approving a change. Reject changes that mutate the same stack through multiple APIs.