Isomorphic React with node.js
Isomorphic what?
Simply, it’s a fancy way of saying we’re going to render our React code server side as well as on the client.
Why?
- Your dynamic JS is now search engine indexable, yay!
- Better overall user experience.
- Performance benefits.
Lets break it down
If you’d like to see the full source code for this article, you can find it here: https://github.com/tomshowell/Isomorphic-react-node
All we’re going to do here is create a component that renders a summary of a news article (title and date) from a static JSON file, both on the server and on the client.
/components/News.jsx
import React from ‘react’;class News extends React.Component {
constructor() {
super();
}render() { let newsArticles = this.props.newsData.map(function(n) { return (
<blockquote>
<p>{ n.title }</p>
<footer>{ n.date }</footer>
</blockquote>
); });return(
<div>
{ newsArticles }
</div>
);
}}export default News;
This is the easy bit. News.jsx takes the JSON data as its props and maps that to a block quote that display the title and the date.
/components/News_Client.jsx
import React from ‘react’;
import ReactDOM from ‘react-dom’;import News from ‘./News’;let props = JSON.parse(document.getElementById(‘props’).innerHTML);ReactDOM.render(
<News newsData={ props } />,
document.getElementById(‘news-mount’)
);
Nothing too unusual here in importing our component and mounting it to a div. This line:
let props = JSON.parse(document.getElementById(‘props’).innerHTML);
will get our JSON data which we pass as props. We’ll cover how this gets populated in routes/routes.js.
/views/index.ejs
<!doctype html>
<html>
<head>
<title>Isomorphic React with node.js</title>
<link href=’https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css' rel=”stylesheet”>
</head>
<body><div class=”container”><h1 id=”main-title”>Isomorphic React with node.js</h1><br /><br /><div id=”news-mount”><%- output %></div></div><script type=”application/json” id=”props”><%- jsonProps %></script><script src=”/newsClient.js”></script></body>
</html>
If you’re this far down the article then you probably know what the above does. The only two things we've added over a traditional React application are
<div id="news-mount"><%- output %></div>
The output tag will take the News components rendered html which we will pass through in our routes.js.
<script type=”application/json” id=”props”><%- jsonProps %></script>
Remember that line in our News_Client.jsx where we parsed JSON out of a div? Well this is where we set it. Again we will pass through jsonProps in our routes.js.
/routes/routes.js — Where the magic happens
If you found the rest of the code simple and easy to follow then this is going to be no different. Let’s take a look at our route.
var React = require(‘react’);
var ReactDOMServer = require(‘react-dom/server’);
var request = require(‘request’);
var url = require (‘url’);News = React.createFactory(require(‘../components/News’).default);module.exports = function(app) {app.get(‘/’, function(req, res) {request(‘http://localhost:8888/news.json', function(err, resp, body) {var html = ReactDOMServer.renderToString(News({ newsData: JSON.parse(body) }));res.render(‘index.ejs’, { output: html, jsonProps: body });
});});}
To render our component server side we first need to include it
News = React.createFactory(require(‘../components/News’).default);
What follows will be wrapped in a request request (? really) that will be executed once we have got our news data.
The following line takes our component and with React’s built in function, renders it to a string, passing the JSON data from the request as the newsData property.
var html = ReactDOMServer.renderToString(News({ newsData: JSON.parse(body) }));
Remember those variables in our view file? This is where we pass them. We will pass our string rendered React component and the JSON data to our view.
res.render(‘index.ejs’, { output: html, jsonProps: body });
That’s it
And we’re done. If you CD to your project directory and run
node app.js
it will start the server up on http://localhost:8888
If you view source (not inspect element), you’ll notice your news titles and dates rendered in the code, good or what!
Additionally, you’ll notice if you comment out
<script src=”/newsClient.js”></script>
In views/index.ejs your news title and dates still get rendered.
I hope you enjoyed this article and can see that isomorphic React doesn't have to be hard! If you have any questions, don’t hesitate to leave them in the comments.