csells / go_router

The purpose of the go_router for Flutter is to use declarative routes to reduce complexity, regardless of the platform you're targeting (mobile, web, desktop), handling deep linking from Android, iOS and the web while still allowing an easy-to-use developer experience.
https://gorouter.dev
441 stars 96 forks source link

Persistent context between routes #379

Closed JakubWasilczyk closed 2 years ago

JakubWasilczyk commented 2 years ago

While working on my app that uses BLoC and GoRouter I came across a problem that basically whenever I push (not go) a new route, the context is being dropped. It might not seem problematic at first, but in case I want to keep my BLoC's already declared on the second route and just build from them, I have to work around it. Don't know if I'm missing something here, or maybe it's a chosen feature, but I would really appreciate if the context could be maintained at least between the parent route and it's children. Code example of my workaround:

Widget build(BuildContext context) {
    return MultiBlocProvider(
      providers: [
        BlocProvider<DeviceControlBloc>(
          lazy: false,
          create: (context) => deviceControlBloc,
        ),
        BlocProvider<BatteryInfoBloc>(
          lazy: false,
          create: (context) => batteryInfoBloc,
        ),
        BlocProvider<ManipoloControlBloc>(
          lazy: false,
          create: (context) => manipoloControlBloc,
        ),
      ],
      child: Builder(
        builder: (context) => IconButton(
          onPressed: () {
            Map<String, dynamic> extra = {
              "device": device,
              "context": context,
            };
            context.push("/device/admin", extra: extra);
          },
          icon: const Icon(Icons.settings),
          ),
        ),
      )

And then in the router builder (it's a child of /device):

          GoRoute(
            name: "deviceAdmin",
            path: 'admin',
            builder: (context, state) {
              if (state.extra is! Map<String, dynamic>) {
                getIt<AppRouter>().router.pop();
              }
              final extra = (state.extra as Map<String, dynamic>);
              DiscoveredDevice device = extra['device'];
              BuildContext extraContext = extra['context'];

              final deviceBloc = extraContext.read<DeviceControlBloc>();
              final batteryBloc = extraContext.read<BatteryInfoBloc>();

              return MultiBlocProvider(
                providers: [
                  BlocProvider.value(
                    value: deviceBloc,
                  ),
                  BlocProvider.value(
                    value: batteryBloc,
                  ),
                ],
                child: DeviceAdminScreen(device: device),
              );
            },
          ),
csells commented 2 years ago

I don't know enough about bloc to help here but perhaps @jopmiddelkamp does.