Hello, my name is Sergey and I am working in web development about 9 years.
I tried a lot of various frameworks and state managers (even Effector, but I'm not sure that you have heard about this STM)
So, last year I'm working with MobX,
and I can say this state manager is something out of the ordinary from the perspective of other state managers.
I mean all modern and hype state managers gives you specific API to work with reactivity data.
Let me illustrate this with comparisons. In Redux Toolkit
, you dance to the rhythm of actions:
dispatch(increment()); // Action -> Reducer -> Update
Zustand takes a more casual approach — like updating a notebook directly
const useStore = create((set) => ({
count: 0,
increment: () => set(state => ({ count: state.count + 1 }))
}));
// In component. Note this.
useStore.getState().increment();
// Direct state mutation (immutable under the hood)
Jotai embraces atomic Zen — you modify individual particles of state:
const countAtom = atom(0);
// In component
const [count, setCount] = useAtom(countAtom);
setCount(prev => prev + 1); // Feels like useState for global state
Meanwhile, MobX whispers: "Just mutate naturally, I'll handle the rest":
class Store {
@observable count = 0;
@action
increment = () => {
this.count += 1; // Direct mutation ✨ Magic happens here
}
}
The Framework vs The Language
Notice a pattern? Redux, Zustand, Jotai — they all dictate reactivity through framework-specific verbs:
-
dispatch()
(Redux) -
set()
(Zustand) -
useAtom()
(Jotai)
You're essentially speaking their language, wrapping your logic in their reactivity protocols.
MobX flips this paradigm. Instead of:
"Hey library, please update state via your API"
It says:
"Hey JavaScript, BE reactive"
Through decorators (@observable
, @action
) or modern makeObservable, MobX extends your vanilla JS objects with reactive superpowers:
class Cart {
items = [];
total = 0;
constructor() {
// after this
makeAutoObservable(this);
// the 'items', 'total' become
// reactive
}
addItem(item) {
this.items.push(item);
this.total += item.price;
}
}
const cart = new Cart();
Why This Matters
- No "Reactivity Tax" Your business logic remains framework-agnostic. A MobX store could work in Vue (theoretically) — it's just a class.
-
Natural Mutation
cart.items[3].price = 20
triggers updates automatically. Noset({...})
gymnastics. - Reactivity as Language Feature MobX isn't a framework — it's a reactive runtime for JS, like turning JavaScript into Vue's reactivity system.
The Tradeoff
With great power comes implicit behavior. While:
reduxStore.count = 5 // ❌ Won't update anything (need dispatch)
mobxStore.count = 5 // ✅ Automatically propagates (if observable)
...this requires understanding MobX's tracking mechanics. You're not calling reactivity — you're being reactive.
Why Choose MobX? The Case for Effortless Reactivity
In the ever-evolving landscape of state management, MobX stands apart not just as a library, but as a paradigm shift. Here’s why it deserves your attention:
1. It Speaks Your Language
MobX doesn’t force you to learn a new dialect of reactivity. Write JavaScript (or TypeScript) as you always have—mutate objects, call methods, compose classes—and let MobX silently wire up reactivity. It’s like upgrading JS with a superpower you didn’t know you needed.
// This isn’t “MobX code”—it’s just your code.
user.name = "Alice";
cart.items.push(product);
No dispatch
, no set
, no boilerplate. Just state.
2. It Trusts You to Mutate
While other libraries treat direct mutation as a sin, MobX embraces it. By decoupling state updates from reactivity mechanics, it liberates you to:
- Refactor fearlessly: Business logic stays pure, untangled from framework APIs.
- Iterate faster: No more "action creators" or "reducers"—just update objects.
- Write tests that focus on domain behavior, not reactivity rituals.
3. It Scales with Your Brain
MobX scales vertically (complex domains) and horizontally (large teams) because:
- OOP-friendly: Model entities as classes, not JSON blobs.
- Precision tracking: Components re-render only when exact dependencies change, not entire branches.
- Zero glue code: No sagas, thunks, or context providers—just observables and reactions.
4. It’s Framework Agnostic (But Loves React)
MobX works seamlessly with React, Vue, Angular, or vanilla JS. Its React bindings (mobx-react-lite
) are so lightweight, you’ll forget they’re there:
// React component
const Cart = observer(() => {
const { items, total } = cartStore; // Auto-subscribes to used fields
return <div>{items.length} items (${total})div>;
});
The observer
HOC is the only concession to React
—everything else is pure logic.
5. It’s Battle-Tested
From enterprise monoliths to nimble startups, MobX powers:
- Microsoft
- Bloomberg’s financial dashboards
- Coinbase’s trading interfaces
Its decade-long evolution proves that implicit reactivity isn’t just clever—it’s robust.
You can read more about companies who uses MobX here
When to Choose MobX?
- 🟢 You value developer experience over rigid structure.
- 🟢 Your domain model is complex and object-oriented.
- 🟢 You want React-like reactivity without React-like constraints.
- 🟢 You’re tired of typing dispatch(action(payload)).
When to Think Twice?
- 🔴 You need strict architectural guardrails (MobX is flexible, not opinionated).
- 🔴 Your team fears “magic” (reactive tracking is implicit).
- 🔴 You’re building a tiny app (overkill for simple state).
The Verdict
MobX isn’t just a state manager—it’s a philosophy. It asks: What if reactivity wasn’t something you call, but something that just happens?
If you crave code that reads like plain JavaScript but behaves like a finely tuned reactive system, give MobX a try. You might just forget you’re using a library—and that’s the highest compliment a tool can receive.
Sergey, signing off. Happy mutating! 🚀