Reputation: 50
I want users on my app to be able to deep link onto profile pages, for example the user might go to "www.myapp.com/#/users/{userId}", and I want my gorouter to be detect the {userId} variable from the uri, and then feed that data into a state notifier, which would fetch details for that user into the app.
So my code looks something like this:
class MyApp extends StatelessWidget {
MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp.router(
routeInformationProvider: _router.routeInformationProvider,
routeInformationParser: _router.routeInformationParser,
routerDelegate: _router.routerDelegate,
);
}
final GoRouter _router = GoRouter(
initialLocation: '/login',
routes: <GoRoute>[
GoRoute(path: '/', builder: (context, state) => LoginSignupPage()),
GoRoute(path: '/login', builder: (context, state) => LoginSignupPage()),
GoRoute(
path: '/projects/:projectShortId',
builder: (context, state) {
var projectShortId = state.params['projectShortId']!;
return Consumer(
builder: (context, ref, child) {
ref
.read(projectStateNotifierProvider.notifier)
.setProjectFromCustomURI(projectShortId);
return ViewProjectPage();
},
);
},
)
],
);
}
But when I run it, initially typing the url "/projects/{userId1}" works fine, but then if I type a different url "/projects/{userId2}", then I get rebuild errors like the following (they're very long, but its just the following with a bunch of update+rebuild framework errors after it):
Error: setState() or markNeedsBuild() called during build.
C:/b/s/w/ir/cache/builder/src/out/host_debug/dart-sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/errors.dart 266:49 throw_
packages/flutter/src/widgets/framework.dart 4549:11 <fn>
packages/flutter/src/widgets/framework.dart 4563:14
markNeedsBuild
packages/flutter_riverpod/src/framework.dart 287:5
[_debugCanModifyProviders]
packages/riverpod/src/framework/provider_base.dart 513:42 <fn>
packages/riverpod/src/framework/provider_base.dart 337:7 setState
packages/riverpod/src/state_notifier_provider/auto_dispose.dart 118:10 listener
packages/state_notifier/state_notifier.dart 225:23 set state
packages/myapp_mvp/state/providers/project_state_provider/project_state_provider.dart 33:5
setProjectFromCustomURI
Upvotes: 3
Views: 1717
Reputation: 54
define a provider for your GoRouter
and inside the provider you can access the ref like this:
final routerProvider = Provider<GoRouter>((ref) {
return GoRouter(
initialLocation: '/login',
routes: <GoRoute>[
GoRoute(path: '/', builder: (context, state) => LoginSignupPage()),
GoRoute(path: '/login', builder: (context, state) => LoginSignupPage()),
GoRoute(
path: '/projects/:projectShortId',
builder: (context, state) {
var projectShortId = state.params['projectShortId']!;
ref
.read(projectStateNotifierProvider.notifier)
.setProjectFromCustomURI(projectShortId);
return ViewProjectPage();
},
)
],
);
});
Upvotes: 1
Reputation: 214
This Error Is Caused When You're Trying to Build A Widget while another one is building its Propably because you called ref.notifier.read in a builder, thats a very bad practice and could slow down your app if You Are setting The State Inside.
may I suggest using navigatorBuilder
from The Go Route Library To Create A Consumer Wrapper For Every Child Widget and creatign A Custom Notifier And State To Store Route Paramters And Then Easily Access Them From Any Consumer Widget Like Your ViewProjectPage
navigatorBuilder: (context, state, child) {
return Consumer(
builder: (_, ref, __) {
ref.watch(authControllerProvider).params = state.params;
return child;},
);
},
answer source from thread : How to define a GoRouter that depends on a Provider?
Upvotes: 1