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

feat: Optionally support current state in BlocListener #4347

Open
zbarbuto opened this issue Jan 28, 2025 · 1 comment
Open

feat: Optionally support current state in BlocListener #4347

zbarbuto opened this issue Jan 28, 2025 · 1 comment
Assignees
Labels
enhancement candidate Candidate for enhancement but additional research is needed pkg:flutter_bloc This issue is related to the flutter_bloc package

Comments

@zbarbuto
Copy link

Description

Given BlocListener is intended to react to changes in state, the current default makes sense: the listener is not called immediately with the current state (as documented).

However, I've come across a few instances where it would be useful to have the option for a listener run once with the current state in addition to future transitions. Generally, instances where you want some feedback in the UI based on state which isn't applicable in a builder or using context.select - like snackbars or route changes.

Alternatives Considered

The current workaround for this is to make sure the widget is stateful and include an initState(). For example, let's say we have a page that is only visible to logged-in users. We want it to re-route users that are not currently logged in in addition to users who log out in future.

class AuthenticatedPage extends StatefulWidget {
  const AuthenticatedPage({super.key});

  @override
  State<AuthenticatedPage> createState() => _AuthenticatedPageState();
}

class _AuthenticatedPageState extends State<AuthenticatedPage> {
  @override
  void initState() {
    super.initState();
    // Handle the current bloc state
    if (!context.read<AuthBloc>().state.isLoggedIn) {
      _signout();
    }
  }

  @override
  Widget build(BuildContext context) {
    return BlocListener<AuthBloc, AuthState>(
      // Handle changes to bloc state
      listenWhen: (previous, next) => previous.isLoggedIn && !next.isLoggedIn,
      listener: (context, state) {
        _signout();
      },
      child: MyAuthenticatedPageContent(),
    );
  }

  _signout() {
    context.router.replace(const UnauthenticatedRoute());
  }
}

Alternatively, we use something like StreamBuilder with a parameter like

stream: context.read<MyCubit>().stream.startWith(context.read<MyCubit>().state);

But this feels way hackier.

Desired Solution

It would clean up a few things to have some sort of optional flag (like startWithCurrentState but probably a better name) that will immediately call the listener once with the current state. With this, we could simplify our widget down to be stateless:

class AuthenticatedPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return BlocListener<AuthBloc, AuthState>(
      // Ensure the listener is checked immediately on creation with current state in addition to future transitions
      startWithCurrentState: true,
      listenWhen: (previous, next) => previous.isLoggedIn && !next.isLoggedIn,
      listener: (context, state) {
        context.router.replace(const UnauthenticatedRoute());
      },
      child: MyAuthenticatedPageContent(),
    );
  }
}

If it makes more sense this could be its own widget rather than a flag on BlocListener.

@felangel felangel added enhancement candidate Candidate for enhancement but additional research is needed pkg:flutter_bloc This issue is related to the flutter_bloc package labels Feb 1, 2025
@felangel felangel self-assigned this Feb 1, 2025
@Gene-Dana
Copy link
Collaborator

The intended use-case for the listener is for side-effects, right?

Having an option to start with initial state seems more like a situation where you want to adjust the approach.

I do think that perhaps this concept of side-effects could be more explicit though.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement candidate Candidate for enhancement but additional research is needed pkg:flutter_bloc This issue is related to the flutter_bloc package
Projects
None yet
Development

No branches or pull requests

3 participants