1. Anuncie Aqui ! Entre em contato fdantas@4each.com.br

[Flutter] Provide a bloc to a portion of the widget tree with go_router

Discussão em 'Mobile' iniciado por Stack, Outubro 10, 2024 às 04:22.

  1. Stack

    Stack Membro Participativo

    I use flutter_bloc for the state management and go_router for navigation and routing in my app.

    Here's a simple version of my router:

    class AppRouter {
    AppRouter._();

    static GoRouter router = GoRouter(
    initialLocation: '/splash',
    routes: [
    GoRoute(
    path: '/splash',
    builder: (context, state) => const SplashPage(),
    ),
    GoRoute(
    path: '/login',
    builder: (context, state) {
    return BlocProvider(
    create: (context) => RegistrationCubit(),
    child: const LoginPage(),
    );
    },
    routes: [
    GoRoute(
    path: 'loading',
    pageBuilder: (context, state) {
    assert(state.extra is RegistrationCubit);
    return DialogPage(
    barrierDismissible: false,
    builder: (_) => BlocProvider.value(
    value: state.extra as RegistrationCubit,
    child: const LoadingDialog(),
    ),
    );
    },
    ),
    GoRoute(
    path: 'confirmAccount',
    builder: (context, state) {
    assert(state.extra is RegistrationCubit);
    return BlocProvider.value(
    value: state.extra as RegistrationCubit,
    child: const ConfirmAccountPage(),
    );
    },
    routes: [
    GoRoute(
    path: 'loading',
    pageBuilder: (context, state) {
    assert(state.extra is RegistrationCubit);
    return DialogPage(
    barrierDismissible: false,
    builder: (_) => BlocProvider.value(
    value: state.extra as RegistrationCubit,
    child: const LoadingDialog(),
    ),
    );
    },
    ),
    ],
    ),
    ],
    ),
    GoRoute(
    path: '/home',
    builder: (context, state) => const HomePage(),
    ),
    ],
    );
    }


    Here's a visualization of my router: [​IMG]

    When the app starts, it first shows a splash page, after that, it shows the login page. The login page is provided with a RegistrationCubit to manage the registration state such as keeping track of email and password. I want to provide the RegistrationCubit to only the routes where /login is their top parent, which means I don't want to provide it to /splash or /home, thus I don't want to declare it at the top of the app. Now if I want to go to the loading page from the login page, I can call context.go('/login/loading'). I also want to have access to RegistrationCubit in the loading page, but now I cannot access it because it is not provided at the top of the app. Searching online, I learned that I can achieve this by passing the RegistrationCubit as a value of the extra parameter like this: context.go('/login/loading', extra: context.read<RegistrationCubit>()) and then I can provide it to the loading page using BlocProvider.value in its GoRoute as you can see in the code above.

    The same method applies for other routes as well, such as /login/confirmAccount and /login/confirmAccount/loading. But I face a problem. Let's say I got to the confirm account page by calling context.go('/login/confirmAccount', extra: context.read<RegistrationCubit>()), and now from this page, I want to go to the loading page, so I call context.go('/login/confirmAccount/loading', extra: context.read<RegistrationCubit>()). But this gives me an error which points to the following portion of the code above:

    GoRoute(
    path: 'confirmAccount',
    builder: (context, state) {
    assert(state.extra is RegistrationCubit);
    return BlocProvider.value(
    value: state.extra as RegistrationCubit,
    child: const ConfirmAccountPage(),
    );
    },


    The error points to the assert line saying that state.extra is not of type RegistrationCubit which means we didn't pass it as extra, and I think that's right, we passed it to the route on top of that, which is the loading page route.

    In the Navigator 1.0 we could easily do that by:

    Navigator.push(
    context,
    MaterialPageRoute(
    builder: (_) => BlocProvider.value(
    value: context.read<RegistrationCubit>(),
    child: SomePage(),
    ),
    ),
    );


    Now my question is how to provide a bloc to any route. Maybe my approach is not the right one at all!

    Continue reading...

Compartilhe esta Página