Skip to content

docs: clarify per-handler event transformer semantics (#3248) - #4819

Open
champ96k wants to merge 1 commit into
felangel:masterfrom
champ96k:docs/transformer-semantics
Open

docs: clarify per-handler event transformer semantics (#3248)#4819
champ96k wants to merge 1 commit into
felangel:masterfrom
champ96k:docs/transformer-semantics

Conversation

@champ96k

@champ96k champ96k commented May 27, 2026

Copy link
Copy Markdown

Status

READY

Breaking Changes

NO

Description

Each registered event handler operates on its own independent stream pipeline. Different handlers with different transformers do not affect each other's execution.

Changes

  • Add Per-Handler Event Transformers section to bloc-concepts.mdx explaining each on<E>() call creates an independent subscription that filters the shared event stream by type and applies its own transformer, with a Dart example showing two handlers with different transformers on the same Bloc.
  • Clarify doc comments in all bloc_concurrency transformers (sequential, restartable, droppable, concurrent) that their guarantees apply per-handler, not across handlers.
  • Clarify that "no event handler overlap" refers to the specific handler using the transformer, not other handlers registered on the same Bloc.

Related Issues

Part of #3248

Type of Change

  • ✨ New feature
  • 🛠️ Bug fix
  • ❌ Breaking change
  • 🧹 Code refactor
  • ✅ Build configuration change
  • 📝 Documentation
  • 🗑️ Chore

Each registered event handler operates on its own independent stream
pipeline. Different handlers with different transformers do not affect
each other's execution.

- Add 'Per-Handler Event Transformers' section to bloc-concepts.mdx
- Clarify doc comments in all bloc_concurrency transformers
- Clarify that 'no event handler overlap' refers to the specific
  handler using the transformer, not other handlers on the same Bloc

Part of felangel#3248
@GhagSagar23

Copy link
Copy Markdown

Thanks for tackling #3248, @champ96k — the per-handler scoping is exactly the right thing to clarify. Sharing a few suggestions that I think would strengthen the PR, cc @felangel for a maintainer steer:

1. Use a snippet component instead of a raw code fence. Every code sample in bloc-concepts.mdx is imported as a <...Snippet /> .astro component (<Code code={...} lang="dart" title="..." />) rather than an inline ```dart block — e.g. DebounceEventTransformerSnippet. The inline fence in the new section is the only one on the page that breaks that pattern. Extracting it into docs/src/components/concepts/bloc/…Snippet.astro keeps it consistent (and picks up the site's syntax highlighting + filename chrome).

2. Make the example self-consistent. The current sample references SearchEvent / SearchState / _onQueryChanged / _onClearSearch without defining them. A sealed class SearchEvent with two final subclasses (matching the sealed-class style the rest of the docs now use) makes it copy-paste-coherent.

3. Answer the follow-up the reporter actually asked. In #3248, @msackman ends on "how do I keep sequential ordering across event types?" — and @federicodesia points at grouping (#3143). The PR explains that handlers are independent but doesn't show the resolution. One extra snippet closes that loop:

class SearchBloc extends Bloc<SearchEvent, SearchState> {
  SearchBloc() : super(const SearchState.initial()) {
    // A single handler on the shared supertype sequences every subtype.
    on<SearchEvent>(_onEvent, transformer: sequential());
  }

  Future<void> _onEvent(SearchEvent event, Emitter<SearchState> emit) async {
    switch (event) {
      case QueryChanged():
        // ...
      case SearchCleared():
        // ...
    }
  }
}

4. Worth a one-liner on the invariant. on<E> may be registered only once per event type (it throws a StateError otherwise) — noting this makes it clear why per-handler scoping is the model rather than an accident.

On the transformer doc comments: the clarifications read well. Minor: the appended paragraph is the same three lines verbatim across all four transformers — folding the scope note into each existing **Note** (and, for sequential/restartable, pointing at the grouping pattern) keeps them tighter.

Happy to open a PR against your branch with these if that's easier, or you're welcome to lift any of it directly — whatever you and @felangel prefer. Thanks again for pushing this forward. 🙏

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants