Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

question: I need to access the latest state of bloc outside of a widget tree in a helper function. #4169

Open
ignicubeLaeeq opened this issue May 16, 2024 · 4 comments
Labels
needs repro info The issue is missing a reproduction sample and/or steps question Further information is requested waiting for response Waiting for follow up

Comments

@ignicubeLaeeq
Copy link

Description
I need to access the latest state of bloc outside of widget tree in a helper function.

Desired Solution
Being able to access the bloc without build context or outside of widget tree.

Alternatives Considered
The only alternative i have right now is to pass the context to helper function and access the bloc state.

@felangel
Copy link
Owner

Hi @ignicubeLaeeq 👋
Thanks for opening an issue!

Can you please provide some additional context regarding what you're trying to achieve? It'd be amazing if you could provide a link to an open source repository that I can checkout and run locally which illustrates the problem you're facing, thanks!

@felangel felangel added question Further information is requested waiting for response Waiting for follow up needs repro info The issue is missing a reproduction sample and/or steps labels May 16, 2024
@ignicubeLaeeq
Copy link
Author

ignicubeLaeeq commented May 23, 2024

Hi @felangel ,
Thank you for your response. Following is a simple example in which i have idToken saved in authbloc which i need to pass in headers for my api requests.

Dio dio(BuildContext context) {
  final dio = Dio(
    BaseOptions(
      baseUrl: Endpoints.backend,
      connectTimeout: const Duration(seconds: 5),
      receiveTimeout: const Duration(seconds: 5),
    ),
  );

  dio.interceptors.add(
    InterceptorsWrapper(
      onRequest: (RequestOptions options, RequestInterceptorHandler handler) {
        final authBloc = context.read<AuthBloc>();
        final token = authBloc.state.token;

        if (token != null) {
          options.headers.addAll({
            'Authorization': 'Bearer $token',
          });
        }

        StyledSnackbar.show('Requesting ${options.uri}');
        return handler.next(options);
      },
      onResponse: (Response response, ResponseInterceptorHandler handler) {
        StyledSnackbar.show(response.toString());
        return handler.next(response);
      },
      onError: (DioException error, ErrorInterceptorHandler handler) {
        StyledSnackbar.show(error.toString());
        return handler.next(error);
      },
    ),
  );

  return dio;
}

I want to do it once on app level and not pass context or token for every api call.
I may need to make the api call from within bloc where i dont have context.
i may need to make the api call from another bloc where i dont have context or token.
Hope this clarifies.
Thanks

@felangel
Copy link
Owner

Hi @felangel , Thank you for your response. Following is a simple example in which i have idToken saved in authbloc which i need to pass in headers for my api requests.

Dio dio(BuildContext context) {
  final dio = Dio(
    BaseOptions(
      baseUrl: Endpoints.backend,
      connectTimeout: const Duration(seconds: 5),
      receiveTimeout: const Duration(seconds: 5),
    ),
  );

  dio.interceptors.add(
    InterceptorsWrapper(
      onRequest: (RequestOptions options, RequestInterceptorHandler handler) {
        final authBloc = context.read<AuthBloc>();
        final token = authBloc.state.token;

        if (token != null) {
          options.headers.addAll({
            'Authorization': 'Bearer $token',
          });
        }

        StyledSnackbar.show('Requesting ${options.uri}');
        return handler.next(options);
      },
      onResponse: (Response response, ResponseInterceptorHandler handler) {
        StyledSnackbar.show(response.toString());
        return handler.next(response);
      },
      onError: (DioException error, ErrorInterceptorHandler handler) {
        StyledSnackbar.show(error.toString());
        return handler.next(error);
      },
    ),
  );

  return dio;
}

I want to do it once on app level and not pass context or token for every api call. I may need to make the api call from within bloc where i dont have context. i may need to make the api call from another bloc where i dont have context or token. Hope this clarifies. Thanks

I highly recommend moving auth token management down into your networking layer. Blocs should generally not know about auth tokens. I recommend using https://pub.dev/packages/fresh_dio. Check out this example for reference https://github.com/felangel/fresh/blob/ce9d5dc202315ef96b6eb04e14d03a667f9bc8f4/packages/fresh_dio/example/packages/jsonplaceholder_client/lib/src/jsonplaceholder_client.dart#L40

@ignicubeLaeeq
Copy link
Author

Thank you for your response.
I have checked out this package, but without enough examples i am reluctant to try it. Moreover i am implementing firebase auth, and since firebase manages the tokens which are short lived, i just need to get the latest token and keep it somewhere in my app. I have been able to that as follows:

  updateToken(
    AuthEventWatchTokenStream event,
    Emitter<AuthState> emit,
  ) async {
    await emit.forEach(
      FirebaseAuth.instance
          .idTokenChanges()
          .asyncMap((user) async => await user?.getIdToken(true)),
      onData: (idToken) => state.copyWith(token: idToken),
    );
  }

Theoretically speaking, is there was a way to access my state without context as per my use case?
Regards

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
needs repro info The issue is missing a reproduction sample and/or steps question Further information is requested waiting for response Waiting for follow up
Projects
None yet
Development

No branches or pull requests

2 participants