I’ll try to keep this short and simple : This post will go over an implementation of asynchronous server side rendering in a React application. I’ll be using React-Router, Mobx and Koa. The application code is over-simplified and meant to be minimal — it’s just a demonstration. Why is this a thing ? React and React-Router come with out-of-the-box server side rendering. Unfortunately — they do not support asynchronous rendering. That means your routes will be handled on the server and your views will be rendered, but if you need to load any data that isn’t on the server (e.g. from a database), that data won’t be available at the time the server does the rendering. When is this needed ? Whenever your application needs some dynamic content (e.g. data from an API) before the pages initially loads. In our example — we’ll have a page that shows information about a comic book character. That information comes from Wikipedia’s API. If that page was shared on Facebook, the Facebook crawler would expect the data about that character to be in the initial response that it gets from the server. If the dynamic data is only rendered on the client side — it would be missing from our Facebook post. Synchronous Rendering ;) Let’s dive in You can find all this code in . I’ll include some code snippets but I recommend using the links to the repository to get a better view. https://github.com/avnersorek/react-async-server-side-rendering Our example application will have two views — the root view (‘/’) which shows a list of comic book characters created by Stan Lee, and another view (‘/characters/:id’) that shows the Wikipedia abstract of a single character. Let’s follow along on what happens when we make a request for a specific character : First stop : React-Router The first place we hit in our flow is . We call which is just React-Router’s method wrapped in a promise (callbacks are 2014). We let React-Router do it’s magic — it will find the components that need to be rendered according to the route. We’ll get back a object, which has the info on what’s about to be rendered. src/app.server.js#renderApp matchRoutes — match so props Setting up the app on the server The props object go to the method. Let’s break that down : initAndRender function* initAndRender(props) {const appStore = yield initStore(props);const initialState = serializeStore(appStore);const app = shared.injectStores(<RouterContext {...props} />, appStore);const componentHTML = renderToString(app);return renderIndex(componentHTML, initialState);} initStore(props) function* initStore(props) {const appStore = new AppStore(); yield props.components.filter(Boolean).map(component => component.wrappedComponent || component).filter(component => component.preServerRender).map(component => component.preServerRender(appStore, props.params)); return appStore;} This is called with since — as the name of this post implies — it will be an asynchronous action. This will create a new object — the store is empty at this stage. Then we’ll go over the components in the props object. These are the components that React-Router found that need to be rendered ( ). We’ll be calling the static method on each component ( ). This is the place for each component to say what it needs before it’s rendered on the server. Let’s look at it on the : yield AppStore They are the classes of the components and not instances preServerRender This is something I made up — not a built in React Component life-cycle method Character component static preServerRender(appStore, params) {return appStore.loadCharacter(params.pageId);} So the Character component will need our to load a character before it renders. We also get the route params, so we know which character ID to use. This method needs to return a Promise, so we’ll know when it’s finished loading the resource. Behind the scenes, this will preform a GET request to Wikipedia’s API. appStore Synchronous from here on That’s it ! That was the whole asynchronous stuff. I’ll cover the rest pretty quick, but it’s ‘standard’ React server side rendering : const initialState = serializeStore(appStore); Will serialize the state. In order for our client-side application to start with the state our server finished with, it needs to be serialized into JSON and planted in the response the server sends. That . Next we render the views : happens here const app = shared.injectStores(<RouterContext {...props} />, appStore);const componentHTML = renderToString(app); Sending the state to the client-side application is not enough. We also want our initial views (HTML) to be rendered according to this state. is just some code shared between the client and the server, utilizing Mobx’s Providers to inject the appStore into our Component instances. is just React-DOM doing it’s thing. s_hared.injectStores_ renderToString return renderIndex(componentHTML, initialState); Now we take our rendered views (HTML) and serialized state (JSON), and . If you have a bigger index.html file, I’d recommend using ejs or jade for this part. inject those into our index.html Don’t forget the client After our initial render, the client-side application takes over. We’ll need to initialize our on the client with the initial state — : appStore this happens in src/app.client.js const initialState = global.window.__INITIAL_STATE__;const appStore = new AppStore(initialState); React will know to take it from there (That’s actually amazing). You’ll even get a warning in your console if the state and HTML you got from the server don’t align. Client from here on The rest of the interaction our user does with the app, will be done on the client-side. The React life-cycle hook to get the next characters : Character component will use the componentDidMount componentDidMount() {const { appStore, params } = this.props;appStore.loadCharacter(params.pageId);} This happens in parallel to the renders, so don’t forget to . support loading states in your components That’s it. I didn’t really go very deep into things, I tried to keep this post short. So if you have any questions please post them here as comments. Thanks ! Edit : Component.render This will work for nested routes, but not for components nested inside components. That’s because those only come into play in when is called. That can be handled by rendering twice as described in react-async-render .