YANA - Yet Another Navigation Approach
YANA provides a convenient way to use declarative state-driven testable navigation. It is Navigator 2.0 without rough edges.
Declarative
The declarative approach separates navigation from UI and business logic. No more Navigator.push
and Navigator.pop
in surprising places.
TreeNavNode buildNavigation(state) => firstOf<AppState>(
when: always,
pages: [
_loginFlow(),
_authedFlow(),
],
)(state);
_loginFlow() => anyOf<AppState>(
when: hasNoUser,
pages: [
materialPage(
when: always,
name: ScreenKeys.authorization,
builder: (_) => const LoginScreen(),
onPopPage: () => false,
)
],
);
_authedFlow() => anyOf<AppState>(
when: hasUser,
pages: [
materialPage(
when: always,
name: ScreenKeys.books,
builder: (_) => const BooksScreen(),
onPopPage: () => false,
),
materialPage(
when: hasSelectedBook,
name: ScreenKeys.bookDetails,
builder: (_) => const BookDetailsScreen(),
onPopPage: () => false,
),
],
);
State-driven
Always predictable screens based on your state. Thanks to Navigator 2.0!
class AppRouterDelegate {
TreeNavNode _navNode;
StreamSubscription<AppState> _storeSubscription;
AppRouterDelegate(store) {
_storeSubscription = store.onChange.listen((event) {
_navNode = buildNavigation(store);
notifyListeners();
});
}
@override
Widget build(BuildContext context) {
final node = _navNode;
final pages = [...node.pages];
return Navigator(
key: navigatorKey,
pages: pages,
onPopPage: (route, result) {
if (node.onPopPage!(route, result)) {
return route.didPop(result);
}
return false;
},
);
}
}
Testable
Simple unit tests guarantee that each state is translated to the expected navigation configuration. Check tests in demos for details.
var pages = buildNavigation(state).pages;
expect(pages, hasLength(1));
expect(pages[0].name, equals(ScreenKeys.authorization));
state.loggedIn = true;
pages = buildNavigation(state).pages;
expect(pages, hasLength(1));
expect(pages[0].name, equals(ScreenKeys.books));
Getting Started
- Add
yana
package to yourpubspec.yaml
- Define
buildNavigation
function - Create your
AppRouterDelegate
that triggersbuildNavigation
for required state changes - Done!
Check examples with redux and provider state management.
Advanced
How to customize a presentation of a page?
Check implementation popUpDialog
for inspiration.
Status
- Production-ready. The library has been used in multiple applications since 2019.
- You can expect breaking changes before the package reaches 1.0.0 based on community feedback.