Re-organising data flow
The in-browser versions of my Tube Tracker application have a very simple data-flow but the model doesn’t quite translate to the server. In the browser data must be fetched via an AJAX request once the app has loaded but an isomorphic app should deliver the complete HTML to the browser.
A React application has one point of access to the component stack–the root either rendered with
renderToString–so data must be provided to the top of the stack and passed down through it. This is contrary to the usual thinking when working with React because data should only be handled by the components that need it.
As the data passes through the stack the components that originally needed to go and fetch data can utilise their
getInitialState lifecycle method to preset and use the data straight away. The rest of the component should remain mostly untouched, only now modified to skip the initial loading state.
The data being provided to the application root on the server also needs to be implemented on the client-side, if the app were to load in the browser without the same data being provided then it would be re-rendered into its initial, empty state. The most straightforward way to transfer the data onto the client-side is to render it into a script element for the application bootstrap to pick up:
React on the server
The component stack is rendered just as it is within the browser but instead of creating a dynamic tree, only a string of HTML is required. React provides the top-level method
renderToString for this purpose and it will only run each component’s
componentWillMount lifecycle methods. Components should translate to the server without causing problems so long as no browser-specific code is executed, so make sure any client-side setup is moved into the
The rest on the server
The final few steps for delivering the initial HTML to the browser are implementation specific but for reference I’ll quickly cover the setup behind the Tube Tracker app.
The application already uses Express to deliver static assets so an additional route was added to process the request and respond with the static HTML. The route makes an API request if necessary and pushes any data returned into a template loaded from the file system:
The template module is extremely basic, it will load the requested file from the file system and replace any named placeholders with the given data. There was no need to employ a more complex templating library because my application will only ever have two pieces of data to inject:
It is no longer possible to create a complete HTML document using React components due to incompatibility between browsers. That may not affect React running on the server but it would be strange to create a component that would not be shared in this context.
I really like React, it’s a brilliant tool, but I like it much more when it’s kept simple.
You can test the completed app right now (note: It’s running on a free account so this link may not be reliable) or head over to GitHub to check out the source code. Please leave a comment or send me a tweet, I’d love some feedback.