Server-side routing with react-router

Let’s set up server-side routing with react-router for a universal web application.

Nov 27, 2016 · 2 min read



In development, we’ve configured nodemon to restart our node application when the JavaScript files have changed. Install it globally, if you haven’t already:

$ npm install nodemon -g

Since we also need to watch files with the extension .jsx, we’ll need to specify the extension watch list:

$ nodemon --ext js,jsx

Now all our JavaScript and React files in the current directory are being watched. As an additional caveat, we can also ignore files in public/ and client.js (since they don’t affect server logic):

$ nodemon --ext js,jsx --ignore public/ --ignore client.js

To stop nodemon, press Ctrl+C.


We’ll be using ReactRouter to set up routing for our universal web app:

$ npm install react-router@3

All our route files will live in the routes/ directory:

$ mkdir routes/

Refactor server.js so that all the route logic can be moved to routes/index.jsx:


Bring in the original route logic to routes/index.jsx (ReactRouter isn’t added yet):


Now add ReactRouter:


So how does ReactRouter server rendering work?

  1. From location (line 15), it gets the full url path from the original request (including the query string).
  2. Then it tries to match (line 8) the location among the routes (line 9).
  3. Whether the match succeeded or failed, the callback is executed (line 16).
  4. If renderProps exists (line 17), then pass it to ReactRouter’s RouterContext (these are ReactRouter’s props).
  5. Otherwise, respond with 404 Not Found (line 23).

There are a few things I left out:

  • If an error exists (line 16), then you should handle it like an Internal Server Error:
if (error) {
  • If redirectLocation exists (line 16), then you should have Express perform a server redirect:
if (redirectLocation) {
redirectLocation.pathname +

For more information on ReactRouter server rendering, check out the official documentation.

Passing Props in ReactRouter

When you refresh the page in the browser, you’ll see that everything works but your title prop is no longer showing.

The reason is because your custom props aren’t passed to ReactRouter before it is rendered on the server-side. Let’s fix that.

Use the Router’s createElement prop to merge ReactRouter’s renderProps with your custom props (lines 20–22):


The way createElement works is that before the Router renders the route component, it will use this function to create the element. Therefore, we’re intentionally merging the RouterContext’s renderProps with our custom props (line 7) using spread attributes.

Now if we refresh the browser page, we can see our title and heading again.

So what’s next? If you haven’t made your web app universal yet, then you should probably do that! In the next tutorial, we’ll go over how to set up client-side routing with ReactRouter. Feel free to check out the code for this tutorial as well as other videos in my React playlist.


Written by

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade