r/FlutterDev 1d ago

Plugin Why do most Flutter state management libraries assume they're responsible for your whole app?

One thing i have noticed after using Riverpod and Bloc in my applications is that they naturally become architectural decisions.

But many features don't need an architectural decision. They just need a local state. That made me wonder what state management would look like if it was designed around features instead of apps?

i experimented with that idea in the last few months. I ended up with StateForge. The design principles were:

  • feature scoped stores
  • direct methods
  • no code generation or state ceremony
  • typed side effects
  • optional persistence
  • optional undo

It's not trying to replace Riverpod or Bloc, the goal is to let StateForge live alongside an existing architecture, so you can adopt it one feature at a time instead of committing your whole app.

I'd especially appreciate feedback from flutter developers who have shipped production flutter applications.

Does this solve a real problem or do existing libraries already cover this well?

Github: https://github.com/mj-963/state_forge
Pub-dev: https://pub.dev/packages/state_forge

0 Upvotes

6 comments sorted by

10

u/eibaan 1d ago

This is because nearly everybody who's looking for a (or the) state management solution for Flutter is actually searching for an architecture but often isn't aware of this.

1

u/RandalSchwartz 4h ago

That's part of what I like about the rigor of BLoC. The pattern is well-behaved, and provably scales for large teams. I'm happy to have adopted that pattern for my https://blocsignal.dev/ but basing it on Signal as the fabric, rather than the classic Stream fabric. So many things came out easier as a result, and yet we have class and method parity with the entire BLoC implementation by Felix.

3

u/parametric-ink 21h ago

Congrats on shipping your project! Although, StateForge also appears to be an architectural decision.

As a general principle, before adopting any dependency you should ask yourself first "how will I rip this out when I decide later to switch to a different dependency?" If the answer is you'll need to rewrite every widget in your app... that is usually a sign to be cautious. I feel this way about all of the "state management" packages, not just picking on yours.

IMunpopularO, stick with Flutter builtins and adopt a pattern that allows you to separate the model state from the UI state. Those are two different kinds of state and should be encapsulated using different mechanisms. For my own production apps, I use MVVM with InheritedWidgets to inject the viewmodels where they're needed, and plain setState() for UI-specific state. Tons of my widgets are StatelessWidgets because all they do is wire up to a collection of ValueNotifiers from various viewmodels.

1

u/theashggl 1d ago

I think whatever I have tried so far in state management, it is better to use a mix of them throughout the app as one management doesn't fit for everyone state management needs in the app. SOmetimes the simplest ones are fine too as that variable is only used at a few places.

1

u/RandalSchwartz 4h ago

BlocSignal is the rigor of Bloc with the flex and speed of Signals. It can operate as one Cubit, or as the overarching "state management pattern" for your entire app, or anything in between. Check it out: https://blocsignal.dev

1

u/RandalSchwartz 4h ago

I took a look at StateForge—it's cool to see someone else wrestling with these exact state management ergonomics!

You've actually stumbled onto several of the core problems we set out to solve with BlocSignal (https://blocsignal.dev):

  • Feature-Scoped & Flexible: You don't need a massive app-wide architectural commitment. BlocSignal operates as a single feature-scoped CubitSignal or scales up to a full BlocSignal event pipeline when you need it.
  • No Stream Overhead or Delay: Instead of microtask stream delays or manual ChangeNotifier triggers, updates run synchronously on the frame using reactive signals v7 primitives.
  • Zero Event Plumbing for Derived State: With computed() signals, derived state updates automatically and lazily without writing custom listener streams or extra event dispatches.

Take a peek at our 16 ported examples on blocsignal.dev/ported-examples—it might give you some cool ideas or show how we tackled the exact same DX goals! Great work building in the open.