Check out myAngular article series with live demos and Facebook group Angular - Advanced Topics

React components - server side and client side

Torgeir "Tor" Helgevold
- JavaScript Developer and Blogger
Published: Sat Feb 28 2015

One of the great things about React is the ability to easily share components between server and browser. In the following post I will demonstrate how to run the same exact React component server side and client side. The server used in this example is NodeJS/Express.

Typically there is a sharp divide between code running on the server vs code running on the client, but JavaScript based development lets us bridge this gap and share code between web server and browser easily.

My blog, SyntaxSuccess, is a hybrid website with SPA like features as well as server side pages. However, to create a consistent look I am sharing certain common elements between the different parts of the application. Ideally this should happen without code duplication, so I figured I'd give React a try and model the site's primary navigation as a shared React component. This means that parts of my site includes the primary nav as a client side component while other parts render the component from the server response.

It turns out that this is relatively straight forward since the component code, through the virtual DOM, is decoupled from the runtime environment. All you need is a little bit of plumbing in order to do the bootstrapping.

As you can see from the code below, the nav component is fairly straight forward:

Component defined in navigationDefinition.jsx

var navComponent = { getInitialState: function() { var navs = []; navs.push({key: 'home', value: 'Home', url:'/#/home'}); navs.push({key: 'angular', value: 'Angular'}); navs.push({key: 'react', value: 'React'}); navs.push({key: 'javascript', value: 'JavaScript'}); navs.push({key: 'unittesting', value: 'Unit Testing'}); navs.push({key: 'dotnet', value: '.Net'}); navs.push({key: 'Favorites', value: 'Favorites', url: '/favorites.html'}); return {navItems: navs, active: 'home'}; }, render: function(){ var current = this.props.current; var navItems = this.state.navItems.map(function(n){ var navStyle = 'navBox'; if(current === n.key){ navStyle += ' activeNav'; } var url = n.url || '/articleList/' + n.key; return <a className="navLink" href={url}> <div className={navStyle}> {n.value} </div> </a> }); return ( <div className="nav col-md-2 hidden-sm hidden-xs">{navItems}</div> ); } }; module.exports = navComponent;

I am taken advantage of CommonJS patterns in order to expose the underlying React object.

Client side integration

The client side integration is easy and probably familiar to most developers with some React experience:

var Navigation = React.createClass(require('./navigationDefinition.jsx')); React.render( Navigation({current:'home'}), document.getElementById('navComponent') );

Note: You should run a compile time tool like browserify to convert the jsx into pure JavaScript before including it on your web page. If you're using Grunt you can add the following grunt task:

module.exports = function(grunt) { grunt.initConfig({ pkg: grunt.file.readJSON('package.json'), browserify: { options: { transform: [ require('grunt-react').browserify ] }, client: { src: ['your-path-to-jsx-files/*.jsx'], dest: 'your-build-folder/nav.js' } } }); grunt.loadNpmTasks('grunt-browserify'); grunt.registerTask('default', [ 'browserify' ]); };

Server side integration

Wiring the component up for server side rendering using Express is also pretty straight forward

1) Install dependencies

npm install react
npm install node-jsx

2) Include dependecies

var React = require('react/addons');
require("node-jsx").install();

3) Create web endpoint and return the component as html

app.get('/articleList/:key', function (req, res){ var navigationDefinition = require('./navigationDefinition.jsx'); var navigationComponent = React.createClass(navigationDefinition); var Nav = React.createFactory(navigationComponent); var markup = React.renderToString( Nav({current:req.param('key')}) ); res.render('articles.html',{navigation:markup}); });

The component will now be returned as part of the page response.

To test the two modes of the left navigation just go to the following links:

Client side rendering (Home)
Server side rendering

Happy coding!

If you liked this article, share it with your friends on social media:

We also have a new Facebook group about advanced Angular topics.

I invite you to follow me on twitter