When building reactive UIs with Bloc, you often need to both rebuild the UI in response to state changes and perform side effects like navigation or showing snackbars. While you can use separate BlocBuilder and BlocListener widgets, BlocConsumer combines both in one convenient widget. This guide covers everything you need to know about BlocConsumer – when to use it, how to configure it, and best practices.
What is BlocConsumer?
BlocConsumer is a widget that combines BlocBuilder and BlocListener. It accepts both a builder (to rebuild the UI) and a listener (to handle side effects). It's particularly useful when you need both capabilities for the same bloc and want to keep the code concise.
Basic Usage
To use BlocConsumer, provide a listener function for side effects and a builder function for UI. The listener runs when the state changes (after the builder), and the builder rebuilds the UI.
Fine‑tuning with listenWhen and buildWhen
Like BlocBuilder and BlocListener, BlocConsumer supports listenWhen and buildWhen to control exactly when each part runs.
When to Use BlocConsumer vs Separate Builder and Listener
| Scenario | Recommendation |
|---|---|
| Both builder and listener are needed for the same bloc | Use BlocConsumer |
| Only builder is needed | Use BlocBuilder |
| Only listener is needed | Use BlocListener |
| Builder and listener logic is complex and you want to separate concerns | Use separate widgets for clarity |
| You need to place builder and listener at different positions in the widget tree | Use separate widgets |
In general, BlocConsumer is ideal when you need both functionalities and they are closely related. For complex UIs where the builder and listener are large or located far apart, separate widgets may be more readable.
Performance Considerations
- Use
listenWhenandbuildWhen– Prevent unnecessary listener calls and rebuilds. - Place
BlocConsumeras low as possible – Only wrap the part of the UI that actually needs the bloc to keep rebuilds localized. - Avoid heavy computations inside
builder– If you need to compute derived data, useSelectororbuildWhen. - For very granular rebuilds, consider using
BlocSelectorinside the builder – This can further reduce rebuilds.
BlocConsumer vs BlocConsumer.value
BlocConsumer also comes with a .value named constructor, similar to BlocProvider.value. It allows you to pass an existing bloc instance instead of creating a new one. This is useful when the bloc is already created elsewhere (e.g., from a parent widget) and you want to reuse it.
Complete Example
Best Practices
- Use
BlocConsumerwhen you need both builder and listener – Avoid unnecessary nesting of separate widgets. - Always provide a
childwhen usingBlocConsumer– Thebuilderreturns a widget; thelistenerdoes not require a child, but the widget itself must return a widget tree. - Use
listenWhento filter side effects – Prevents unnecessary navigation or snackbar calls. - Use
buildWhento filter UI rebuilds – Improves performance. - Place
BlocConsumeras close to the UI that depends on the state as possible – Keeps rebuilds local. - Separate concerns – If the builder and listener are very large, consider splitting into smaller widgets for readability.
Common Mistakes
- ❌ Using
BlocConsumerwhen only builder or only listener is needed – Adds unnecessary complexity. ✅ UseBlocBuilderorBlocListenerindividually. - ❌ Forgetting to handle all states in builder – UI may break. ✅ Always define a fallback or handle all possible states.
- ❌ Calling
emitinsidelistener– This would cause an infinite loop. ✅ Uselistenerfor side effects, not for state changes. - ❌ Placing
BlocConsumertoo high in the tree – Rebuilds more than necessary. ✅ Place it as low as possible. - ❌ Not using
listenWhenorbuildWhenwhen state changes frequently – Performance degradation. ✅ Use filters to limit rebuilds and listener calls.
Next Steps
Now that you've mastered BlocConsumer, explore other Bloc topics:
- BlocProvider – Providing blocs to the widget tree.
- BlocBuilder & BlocListener – In‑depth look at each.
- Bloc Performance Optimization – Advanced tips.
Conclusion
BlocConsumer is a versatile widget that combines the power of BlocBuilder and BlocListener. It simplifies your code when you need both UI rebuilds and side effects for the same bloc. By using listenWhen and buildWhen, you can keep your app performant and your UI responsive. Use it wisely to build clean, maintainable Flutter applications.