1

I'm using flutter_bloc and go_router.

This is an implementation of multiple-page-form, for this demo it's just 2 pages. I used ShellRoute to provide MultiFormBloc to 2 routes, so that both routes will have access to the same MultiFormBloc instance.

In the redirect method in step 2 route, I wanted to conditionally redirect user back to step 1 based on if user has completed step 1 or not (since that there's a possibility that user can request for step 2 page directly without finishing step 1, e.g. entering /step2 in the browser's search bar)

However, it seems like MultiFormBloc is not injected in the BuildContext provided in the redirect method.

How can I access bloc injected deep in the tree (not top level in main.dart) in the redirect method? Or is there a better way to do this conditional logic?

...

ShellRoute(
  builder: (context, state, child) {
    // Use [ShellRoute] for the sole purpose of providing [MultiFormBloc] to
    // 2 routes. So that the 2 routes have access to the same bloc instance.
    return BlocProvider(
      create: (context) => MultiFormBloc(),
      child: child,
    );
  },
  routes: [
    GoRoute(
      name: 'step1',
      path: 'step1',
      builder: (context, state) => Step1(),
      routes: [
        GoRoute(
          name: 'step2',
          path: 'step2',
          builder: (context, state) => Step2(),
          redirect: (context, state) {
            // If user haven't completed form 1, redirect user to form 1 page.
            // Error accessing [MultiFormBloc], bloc not injected in context.
            if (context.read<MultiFormBloc>().state.step1Value == null) {
              return '/step1';
            }
            return null;
          },
        ),
      ],
    ),
  ],
),

...
Chwizdo
  • 150
  • 1
  • 7

1 Answers1

0

If you want to pass the same bloc to independent rotes you have to pass it’s value instead. You first create your bloc final myBloc = MyBloc(). Then, pass its value to each route.

// When you want to navigate to Step1()
BlocProvider.value(
    value: myBloc,
    child: Step1(),
)

// When you want to navigate to Step2()
BlocProvider.value(
    value: myBloc,
    child: Step2(),
)

Now, both Step1() and Step2() routes share the same bloc instance and have access to the same state.

Younss AIT MOU
  • 871
  • 7
  • 14
  • This doesn't work because I wanted to create the instance of BLoC only at a certain route forward, not at the top level. So the BLoC instance will get disposed after popping off the route it was provided. – Chwizdo Sep 26 '22 at 05:08