State Management Example
State management answers a single question: when shared data changes, how does every part of the interface that uses it stay correct. This example builds a tiny central store with subscribe and update, then connects three readers that all react to one change. It uses a Backbone Model as the store, since a model already provides change events.
For the bigger picture, see state management in frontend architecture and how the patterns evolved in state management evolution.
What you'll learn
What this example builds
The example holds a shared counter in one store and wires three separate readers that all update when the counter changes, each from the same single source of truth.
The behaviour you will see
Updating the store once notifies every subscriber, so all three readers print the new value without being called individually. There is exactly one place the data lives and one way to change it, which removes the question of which copy is correct.
The central store
A Backbone Model makes a capable store because it already holds attributes and emits change events.
The store object
var store = new Backbone.Model({
count: 0,
user: null
});
Subscribing to changes
Any number of readers can listen to the store and react when their slice of state changes.
Three readers, one source
store.on("change:count", function (model, value) {
console.log("A sees " + value);
});
store.on("change:count", function (model, value) {
console.log("B sees " + value);
});
store.on("change:count", function (model, value) {
document.title = "Count: " + value;
});
Updating state in one place
State changes through a single controlled call rather than being mutated from many places.
One way to change data
function increment() {
store.set("count", store.get("count") + 1);
}
increment(); // every subscriber above runs once
Because all updates go through set, the flow of change is easy to trace, the same discipline described in state management evolution.
Deriving values from state
Values that depend on state should be computed from it, not stored separately.
Computed, not duplicated
function isEven() {
return store.get("count") % 2 === 0;
}
Keeping isEven as a function of count means it can never disagree with the source. Storing a separate even flag would create a second copy that has to be kept in sync, which is exactly the bug a single source of truth is meant to prevent.
Common pitfalls
State bugs share a few root causes.
What usually goes wrong
The most common is keeping the same data in two places, so they drift apart. Store it once and derive the rest. The second is mutating state directly rather than through the store, which skips the change events subscribers need. The third is putting too much in a global store when local component state would do, which makes the application harder to reason about. The trade-offs are covered in state management.
Frequently Asked Questions
How do I share state between components?
Keep the data in one central store and let each component subscribe to it. When the store changes it notifies every subscriber, so all of them update from the same single source of truth.
Why use a single source of truth for state?
So there is never a question of which copy of the data is correct. One place holds the value, one path changes it, and everything else is derived, which removes a whole class of synchronisation bugs.
Should I store computed values?
No. Derive them from state with a function instead. A stored copy of a computed value becomes a second source that can drift out of sync, which is the problem a single source of truth avoids.
When should state be global versus local?
Use global state only for data genuinely shared across many parts of the app. Data used by one component should stay local, since an oversized global store makes the application harder to reason about.
Read next: the event-driven UI example, or back to the Examples hub.
Want the patterns behind it?
The state management guide covers stores, single source of truth, and trade-offs.
Read: State Management →