Introduction
MobX is a powerful state management library that makes state synchronization efficient and straightforward. While most MobX tutorials focus on global state management, local observable state in observer components is an equally important pattern that can simplify your React components while maintaining reactivity.
What is Local Observable State?
Local observable state refers to observable state that is scoped to a single component instance rather than being shared globally. This is created using MobX's makeObservable
, makeAutoObservable
, or observable
directly within a component.
import { makeAutoObservable } from 'mobx';
import { observer } from 'mobx-react-lite';
const Counter = observer(() => {
const state = makeAutoObservable({
count: 0,
increment() {
this.count++;
},
decrement() {
this.count--;
},
get double() {
return this.count * 2;
}
});
return (
<div>
<button onClick={state.decrement}>-</button>
<span>{state.count}</span>
<button onClick={state.increment}>+</button>
<div>Double: {state.double}</div>
</div>
);
});
When to Use Local Observable State
1. Component-Specific State
When you have state that's only relevant to a single component or its children, local observable state keeps your logic co-located and encapsulated.
2. Complex Local State
For components with:
- Multiple interdependent state values
- Derived values (computed properties)
- Actions that modify multiple state values
3. Form Management
Forms with many fields, validation, and complex interaction patterns benefit greatly from local observable state:
const FormComponent = observer(() => {
const form = makeAutoObservable({
values: { name: '', email: '' },
errors: {},
get isValid() {
return !Object.keys(this.errors).length;
},
setField(name, value) {
this.values[name] = value;
this.validateField(name);
},
validateField(name) {
// validation logic
},
submit() {
// submission logic
}
});
return (
<form onSubmit={form.submit}>
<input
value={form.values.name}
onChange={(e) => form.setField('name', e.target.value)}
/>
{/* other fields */}
</form>
);
});
4. Avoiding Prop Drilling
When you need to share state between a parent and deeply nested children, but the state isn't needed globally.
5. Performance Optimization
Local observables can help minimize re-renders since only the observing component reacts to changes.
Why Use Local Observable State?
1. Encapsulation
Keeps state and logic close to where it's used, making components more self-contained and easier to reason about.
2. Reactive Benefits
You get all of MobX's reactivity (computed values, automatic tracking, efficient updates) without global state overhead.
3. Cleaner Code
Eliminates the need for useState
and useMemo
hooks for derived values - MobX handles this automatically.
4. Testability
Local state is easier to test in isolation since it's not tied to a global store.
Best Practices
Use
makeAutoObservable
for most cases - it's concise and automatically infers everything.Initialize properly - Create the observable in the component body but outside any hooks or callbacks.
Combine with hooks when needed:
const Component = observer(() => {
const [externalData] = useState(/*...*/);
const localState = useMemo(() => makeAutoObservable({ /*...*/ }), [externalData]);
// ...
});
For class components, use
makeObservable
in the constructor.Consider disposal for any reactions or side effects:
useEffect(() => {
const disposer = autorun(() => {
// reaction logic
});
return () => disposer();
}, []);
When Not to Use Local Observable State
State needs to be shared widely across the app - use a global store instead.
Very simple state -
useState
might be sufficient for trivial cases.Server-side rendering - Be cautious as local state won't persist between server and client.
Conclusion
MobX local observable state in observer components offers a powerful middle ground between simple useState
and full global state management. It brings MobX's reactivity to component-local state while maintaining clean encapsulation. This pattern shines for complex component state, forms, and cases where you want reactive updates without global state overhead.
By understanding when and how to use local observable state effectively, you can write more maintainable, reactive React components with MobX.
Top comments (0)