Architecting Your App with React
In May of last year, Facebook released an open source library for building frontend components called React. It's built around some rather unorthodox philosophies about the browser and application structure, but over time it has gained quite a bit of steam as many developers see the advantages it offers. One of the most striking distinctives of React is the virtual DOM that it provides in order to minimize changes to the actual browser DOM and provide impressive rendering performance.
React is not a full MVC framework, and this is actually one of its strengths. Many who adopt React choose to do so alongside their favorite MVC framework, like Backbone. React has no opinions about routing or syncing data, so you can easily use your favorite tools to handle those aspects of your frontend application. You'll often see React used to manage specific parts of an application's UI and not others. React really shines, however, when you fully embrace its strategies and make it the core of your application's interface.
Avoid the DOM wherever possible
React provides a virtual DOM implemented entirely as JavaScript classes. This is so that you can make numerous updates to your applications element tree without actually incurring the overhead of browser DOM manipulations. With modern engines such as V8, JavaScript is extremely fast. So fast, in fact, that it's entirely possible for you to render your entire application every time your data changes, eliminating the need for you to manipulate elements in place or manage two-way binding. React will periodically diff the virtual DOM against the browser DOM, and make the minimal set of changes needed to bring the browser DOM into sync.
One-way data flow
When the cost of rendering is so dramatically reduced, you are now free to take a much more declarative approach to managing your interface. Instead of implementing complex manipulations to update your elements in place and keep multiple sources of state in sync as data changes, you can keep your state in one place and describe your interface based on that. As things change, your component reacts by re-rendering.
When your whole application is build around this, you can pass immutable data from the top level down to various child components and then re-render your whole application from the top down when anything changes. It changes how you think about your application and often ends up simplifying things a great deal.
The browser as a rendering engine
This is a pretty radical departure from the strategy of most frontend MVC frameworks, which strive to reduce re-rendering as much as possible by automatically manipulating data in place with two-way binding. When I first started looking into React, I wasn't convinced. The turning point for me was when I watched a video where Pete Hunt compared React to the Doom 3 rendering engine.
In the diagram, the game state is fed into a "frontend" layer of logic and abstraction over the lower-level graphics code. This leads to the creation of a "scene intermediate representation" which describes what the user should see. This is given to the "backend", which takes that representation and turns it into OpenGL operations, which renders the scene with the graphics card. React works in a very similar way.
When something changes in the application state due to browser or realtime events, your application takes that state and passes it down to your components to create an intermediate representation of your user interface using the virtual DOM. No actual changes are made to the browser DOM right away, however. React periodically takes the virtual DOM and calculates the DOM operations needed, similar to how the game engine takes the scene IR and determines what OpenGL operations are needed. The browser takes the DOM and renders it to the screen.
In both the browser and game engine, the slow part is actually rendering the intermediate representation to the screen. You can make many small changes to the virtual DOM very quickly. React optimizes the part that matters, so you don't have to sacrifice performance for code quality.
More resources
In Part 2, I'll demonstrate how we use React to put these philosophies into practice. I'll share how we set up a top-level application component that renders an interface composed of smaller components with different responsibilities, and I'll describe how we integrate routing and data syncing into this structure.
In the meantime, take a look at the resources below if you would like to know more about React and how it works.
- The React homepage
- Videos
- Examples
- The React Google Group
- #reactjs on Freenode - the official IRC channel, which is quite active.