Backbone.js Data Flow
Click a star to favourite an item, and three things should happen: the data records it, the star fills in, and a counter ticks up somewhere else on the page. The bugs start when those three try to update each other directly. Backbone avoids that by sending every change through one path, and once you can trace that path, the whole app becomes predictable.
This guide draws the path end to end. It pulls together the events, view lifecycle, and sync guides into a single mental model of how a value travels from a click to the screen and back to the server.
What you'll learn
The one loop: action, model, event, view
At the centre of every Backbone screen is a short, repeating cycle. Something happens, the model is updated, the model announces the update, and the view redraws to match. Learn to see this loop and most "why did the UI not update" questions answer themselves.
Why the model is the single source of truth
The rule that makes the loop work is simple: the model holds the truth, and the DOM is just a picture of it. You never read state back out of the HTML, because the moment you do, you have two copies that can disagree. There is one authority, and everything else reflects it.
From a user action to model.set()
The loop begins when a handler runs, and the handler's job is narrow: it updates data, not the screen. Reaching into the DOM here to flip a class would break the cycle before it starts.
Update data, not the DOM
events: { 'click .like': 'like' },
like: function () {
this.model.set('liked', true); // change the data, not the DOM
}
Notice what the handler does not do: it never touches the star element. It changes one attribute and trusts the rest of the loop to update the view. That single discipline is what keeps the data and the display from drifting apart.
From change events to a re-render
Setting an attribute fires a change event, and that event is the hinge of the whole system. A view that subscribed to it redraws itself; a view that did not, sits still. This is the same wiring from the events and lifecycle guides, now doing real work.
Listening with listenTo, rendering once
initialize: function () {
this.listenTo(this.model, 'change', this.render);
}
With that one line, every future set on the model triggers a fresh, idempotent render. The view stays a pure function of the model: give it the same data and it produces the same DOM, every time, with no leftover state from the previous render.
Collections: many models, one list view
Scale the loop from one model to many and you have a collection. The same pattern holds, except now the events that matter are about membership: a model joining, leaving, or the whole set being replaced.
How list views stay in sync
initialize: function () {
this.listenTo(this.collection, 'add remove reset', this.render);
}
A list view listens for add, remove, and reset and redraws when the membership changes, while each row listens to its own model for content changes. Responsibility splits cleanly: the list owns which rows exist, and each row owns what it shows.
The server in the loop
The loop is not sealed inside the browser; the server is part of it. Data flows out when you persist and flows back in when you load, and both ends meet at the same model rather than at the view.
Round-tripping through the server
this.model.save(); // data flows out: POST or PUT
this.collection.fetch(); // data flows in: GET, views re-render on 'sync'
A save sends the model's current state outward; a fetch brings fresh state in and, through the sync event, kicks the same render path you already use. The server becomes just another source that updates the one source of truth, as covered in the sync guide.
One direction beats two-way binding
It can feel tempting to wish for automatic two-way binding, where editing an input silently rewrites the model and back again. Backbone's deliberate, one-directional path is the better deal, because every change has exactly one route you can put a breakpoint on.
Why predictable flow scales
When data only ever moves action to model to view, debugging is tracing a line, not untangling a web. This is the same realisation that produced Flux and the reducers in Redux, and the reason React leans on one-way data flow. Backbone got there first, by simply not adding the magic. With the loop understood, the final foundations topic, routing, adds the one more input that drives it: the URL.
Frequently Asked Questions
Is data binding in Backbone one-way or two-way?
Backbone has no automatic two-way binding. You wire the flow yourself: a view handler writes to the model, and the model's change event drives the view to re-render. That explicitness is intentional and makes the path of an update easy to follow.
What is the single source of truth in a Backbone app?
The model and collection hold the truth; the DOM is only a projection of them. Always read and write state through the model, never scrape it back out of the rendered HTML, or the two will drift apart.
How does a change in one model update the screen?
Calling model.set fires a change event. A view that listened with listenTo runs its render in response, and the DOM is rewritten to reflect the new data. The view never edits the DOM directly from the handler.
How is Backbone's data flow related to Flux or Redux?
They share the core idea: a single source of truth and updates flowing in one direction. Backbone wires that loop by hand with models and events, while Flux and Redux formalise it with stores and dispatched actions.
Read next: Backbone.js Routing Basics, the last foundations guide, or revisit What is a Model? for the source of every change.
Watch the loop in a full app
Data flow ties the parts together. The complete guide shows Models, Views, Routers, and Collections working as one.
Explore the Backbone Guide →