Skip to main content

The Secrets of React's Virtual DOM

Pete Hunt (Smyte)
Average rating: ****.
(4.75, 16 ratings)

React, the new open-source JS library from Facebook and Instagram, is a different way to write JavaScript apps. When it was introduced at JSConf in May, the audience was shocked at some of its design principles. One sarcastic tweet from an audience member ended up describing React’s philosophy quite accurately: https://twitter.com/cowboy/status/339858717451362304.

I’ll start with a brief introduction to React (focusing on how to build the stereotypical todo list app) and dive into three controversial topics:

1. Throwing out the notion of templates, and mixing your markup and JS

We think that template languages are underpowered and are bad at creating complex UIs. Furthermore, we feel that they are not a meaningful implementation of separation of concerns — markup and display logic both share the same concern, so why do we introduce artificial barriers between them? We think there are much better and more flexible ways to separate concerns without reducing modularity and code reuse while still allowing designers and contractors to contribute.

For example, at Instagram we migrated from the standard Mustache/Backbone/jQuery trio to React with a little bit of Backbone. One big benefit of this move was that we could express our display logic with pure JS, so we can use all the standard object-oriented and procedural techniques to reuse code and functional concepts like map() and filter() to render UIs rather than rely on the primitives provided by Mustache. We found ourselves fighting Mustache more than appreciating it, and the ability to move that code to JS was wonderful. Additionally, designers are still able to contribute just as they were with a more traditional templating solution.

2. Re-rendering your whole application when data changes

In the old days of writing server-rendered Web apps, when the data changed you just hit the refresh button. You didn’t have to futz around with writing custom code to bring the view up-to-date with the state of the data. With JS applications you do, since refreshing the page is slow and you lose the state of the application. React brings this conceptual model to JS apps. It makes rerendering your application very cheap and maintains the state of the UI when it is rerendered.

At Instagram we again had this problem with templates. Template languages express the initial render of your application, and you’re responsible for manually mutating the state of the UI when your backing data changes and events occur. You can think of template languages as a function that defines your data at time=0; with React, you define your UI in a similar way — declaratively — except it specifies how your UI looks at any point in time, not just the initial load. React takes care of managing UI updates for you so you don’t have to do it yourself. When we were only using jQuery to do the updates at Instagram, we soon found ourselves with a bunch of jQuery-spaghetti.

This isn’t a fundamental problem with Mustache. There are issues with the fundamental idea of template languages as they’re used today. There is a time and place for templates (like simple static pages and perhaps emails), but it’s not on the web front-end anymore.

3. A lightweight implementation of the DOM and events

React includes a lightweight implementation of the DOM and events system. Manipulation our in-memory representation of the DOM is faster and more efficient than manipulating the real browser DOM, and our events system implements all events in a cross-browser way, including bubbling. You even get some HTML5 events in IE8!

Implementing the DOM and events lets us do some cool things. First of all, it makes React very fast and efficient — React apps can easily run at 60fps, even on mobile devices. Throwing out your whole UI and re-rendering it every time the data changes is normally prohibitively expensive, but with our fake DOM it’s actually quite cheap: we can quickly diff the current state of the UI with the desired state and compute the minimal set of DOM mutations (which are quite expensive) to achieve it. We can also batch together these mutations such that the UI is updated all at once in a single animation frame.

Additionally, because React only deals with a fake DOM, we can transparently render on the server. We can generate HTML in pure Node (without a DOM implementation like phantom or jsdom) and send it down to the client. React is smart enough to recognize that the markup is already there, and will only add event handlers.

We’re also experimenting with running parts or the whole application in a web worker, and using React to drive native Android and iOS views.

We are trying to push the limits of what’s possible on the web with React. I’m excited to share our ideas and passion for this with some like-minded folks :)

Photo of Pete Hunt

Pete Hunt

Smyte

Hacker at Facebook, currently doing web stuff at Instagram. Formerly Facebook Photos and Videos lead.

Core team on http://facebook.github.io/react/ and http://github.com/facebook/huxley