bloc icon indicating copy to clipboard operation
bloc copied to clipboard

feat: BlocListener that trigger once but with return specific prop like BlocSelector

Open erlangparasu opened this issue 1 year ago • 3 comments

Description

I'm always frustrated when using BlocListener with call some property in listenWhen:, but wrong calling propertiy on listener:.

Desired Solution

BlocListener that trigger once but with return specific prop like BlocSelector does.

Alternatives Considered

~

Additional Context

~

erlangparasu avatar Jan 15 '24 02:01 erlangparasu

Hello @erlangparasu, could you expand more on what the expected behavior should look like, or can you share the particular use case you are having trouble with?

elianortega avatar Jan 15 '24 23:01 elianortega

BlocListener<DashboardCubit, DashboardState>(
  listenWhen: (previous, current) {
    return previous.saveEvent != current.saveEvent;
  },
  listener: (context, state) {
    final event = state.saveEvent;; // <--- right
    // check event, todo show snackbar
  },
),

Sometimes I make typos when typing the events I mean. So then i got the wrong result.

BlocListener<DashboardCubit, DashboardState>(
  listenWhen: (previous, current) {
    return previous.saveEvent != current.saveEvent;
  },
  listener: (context, state) {
    final event = state.otherEvent; // <--- wrong
    // check event, todo show snackbar
  },
),

That might help to reduce errors such as typos, here are the features I expected.

BlocListener<DashboardCubit, DashboardState>(
  selector: (state) {
    return state.saveEvent;
  },
  selectListener: (context, event) {
    // check event, todo show snackbar
  },
),

erlangparasu avatar Jan 17 '24 01:01 erlangparasu

I implemented that behavior using a function as a BlocListener wrapper:

File: custom_bloc_listener.dart

import 'package:flutter/widgets.dart';
import 'package:flutter_bloc/flutter_bloc.dart';

BlocListener<B, S> customBlocListener<B extends StateStreamable<S>, S, T>({
  required T Function(S state) selector,
  required void Function(BuildContext context, T selectedState) listener,
  B? bloc,
  Key? key,
  Widget? child,
}) {
  return BlocListener<B, S>(
    listenWhen: (previous, current) {
      return selector(previous) != selector(current);
    },
    listener: (context, state) {
      final selected = selector(state);
      listener(context, selected);
    },
    bloc: bloc,
    key: key,
    child: child,
  );
}

How to use:

// ...

customBlocListener<DashboardCubit, DashboardState, DSavedEvent?>(
  selector: (state) {
    return state.savedEvent;
  },
  listener: (context, selected) {
    // do stuff with selected state
  },
  child: SizedBox(),
),

// ...

erlangparasu avatar Jan 22 '24 23:01 erlangparasu

Sounds like you resolved this so I'm closing this for now. If this is still an issue let us know and I'm happy to take a closer look 👍

felangel avatar Apr 20 '24 04:04 felangel