Open klondikedragon opened 2 years ago
I'm having this exact problem and I'm grateful there is some serious work to improve it.
I believe this might have something to do with this comment? https://github.com/lulupointu/vrouter/issues/77#issuecomment-851869374
This enhancement is motivated by the code example here from #32 to use
VNester
and sync bottom nav bar and nested tab bar with routes while preserving state.While the code example from the linked comment above works, you have to repeat the whole
VNester
and thewidgetBuilder
(only varying thecurrentIndex
in the constructor to the widget). This gets pretty cumbersome if you have more complex nested routes withVGuard
or as the nesting level goes 3-deep in a more complex app.The reason why the whole
VNester
has to be repeated in the example is that there is no way to associate with the child widget the tab index (even a mixin to Widget won't work, as the actual child widget is wrapped in aBuilder
and cannot be accessed directly from thechild
parameter passed to thewidgetBuilder
function).This PR adds the concept of an optional
customValue
dynamic value toVRouteElement
, and then an optional second type ofwidgetBuilder
that will take(child, customValue)
instead of just(child)
.VNester
is enhanced to then search for and provide the "nearest" customValue on the matched route to the child to thewidgetBuilder
(logic to do this only happens ifwidgetBuilder
has the new type -- the old type is still accepted for backwards compatibility as well). This simplifies the code example to the following:Show modified "advanced" example that uses `customValue`
```dart import 'package:flutter/material.dart'; import 'package:vrouter/vrouter.dart'; void main() { runApp( VRouter( debugShowCheckedModeBanner: false, routes: [ VNester( path: '/', widgetBuilder: (child, customValue) => MyScaffold(child, currentIndex: customValue as int), nestedRoutes: [ VWidget( path: null, key: ValueKey('Home'), customValue: 0, widget: HomeScreen(), stackedRoutes: [ VNester( path: null, widgetBuilder: (child, customValue) => MyTabs(child, currentIndex: customValue as int), nestedRoutes: [ VWidget( path: 'red', customValue: 0, widget: ColorScreen(color: Colors.redAccent, title: 'Red')), VWidget( path: 'green', customValue: 1, widget: ColorScreen( color: Colors.greenAccent, title: 'Green')), ], ), ], ), VWidget( path: 'profile', customValue: 1, widget: ProfileScreen(), stackedRoutes: [ VWidget(path: 'settings', widget: SettingsScreen()) ], ), ], ), ], ), ); } class BaseWidget extends StatefulWidget { final String title; final String buttonText; final String to; BaseWidget({required this.title, required this.buttonText, required this.to}); @override _BaseWidgetState createState() => _BaseWidgetState(); } class _BaseWidgetState extends StateHowever, it is causing an issue where after navigating back and forth between different nested routes now that there is only a single VNester, flutter (2.8.0) throws the error:
(Note that there is a RenderIndexedStack exception getting thrown sometimes too, but that wasn't happening in the full-scale app, it was just the Duplicate GlobalKey exception that was occurring whenever changing the route to a different tab at the same "nesting level" as the current route.)
And inspecting the debug label of the
GlobalKey
, it is the global key of the top-most level VNester. Using multiple VNesters like the original example (even with customValue) doesn't have this problem, so it doesn't seem like the customValue changes cause this directly, but it might be something unexpected with how this is working now that only a single VNester is needed at each level. I'm not a flutter expert (yet!), and so was hoping @lulupointu you might have some insights why this might be happening / how to fix it.I'd also love your feedback on the general direction of this PR as well! At first I tried to add a custom value chain (similar to name) in
VRoute
, but this was complex and also was difficult to know exactly which customValue should be passed towidgetBuilder
(especially when there are multiple nested VNester). This PR is the second attempt that is simpler where it just searches the element list (which does have only the list of child route elements at the point of VNester, so it was both simpler and worked with all levels of nesting).In the meantime, I made a custom
VRouteElementBuilder
that generates the multipleVNester
(one for each tab) so that it removes boilerplate / duplicate code, and still works with the current vRouter as released. In case it's useful to anyone:Show code for TabbedNester
```dart class TabbedNesterEntry { final List