The Philosophy
React is a JavaScript library that has been built to create user interfaces for large applications with data that changes over time. A React website is made from a nested series of what are called React components.
In React, a component is an object that is given some properties and is expected to always render the same output to the browser from the same properties (this is key to the whole Isomorphic thing which I’ll talk about later), so as a result there is no randomizing, or logic, inside of a component.
There are some “hardcore” React developers out there who prefer to code it manually the long way, but some people enjoy pain too!
Inside each component we have a main function, which is named render(). This function is called every time that React thinks something may have changed and wants to check what the output is going to be. This rendered component isn’t directly rendered to the browser’s DOM. Instead, it’s rendered to a shadow DOM, and only the difference between the current DOM and the Virtual DOM are actioned. This results in extremely fast updates as node creations and changes are kept to an absolute minimum.
Data binding can be done either top-down, meaning that if a value changes it isn’t reflected on a parent automatically, or bottom-up. In larger applications it can be beneficial to go bottom-up, but we’ll be going top-down in the demo below, as it is simpler to learn. In this method, functions are passed into components to notify it when something gets changed.
JSX
React comes with some syntactical sugar to ease your template creation. As our templates are now technically pure JavaScript, this is the artist known as JSX. All this sugar really provides is conversions from the following:
<div>Hello {this.props.name}</div>;
To the following:
React.createElement("div", null, "Hello ", this.props.name);
It’s not lot of code doing it the second way, but I find I couldn’t live without JSX now! There are some “hardcore” React developers out there who prefer to code it manually the long way, but some people enjoy pain too!
Flux
As React is totally different from everything else, how you implement it and structure your JavaScript is specified with Flux, an architectural pattern for making client-side applications. You don’t need Flux for but it is definitely recommended!
If you’ve ever tried to research Flux, you’ve probably found this image:
It’s very confusing!
The basic flow is this: Components sign up to a store (think of this as a database with some local collections) to receive events when something in the store changes. If someone clicks on a button, this button then triggers an event in the “Action Creators” to do something such as “get some data”. This in turn will talk to the API asynchronously, and will then give the store the new data. Finally, the store will emit an event that new data is ready.
Isomorphic Rendering
Isomorphic rendering is a fancy name for something which is a simple concept. It’s where both server and the browser utilize the same templates. Simple isn’t it? It’s a great concept, which we as an industry should have started utilizing sooner!
Whilst the browser is loading its JavaScript assets, HTML has already been rendered before the onDomReady event has fired.
Implementation
How it Works in General
The templates are pre-rendered on the server, and are then injected into the HTML response of the page. This also includes a copy of the dynamic properties which were used to render the page so they can run in the browser and get the same output. This means that whilst the browser is loading its JavaScript assets, HTML has already been rendered before the onDomReady event has fired, whereas with normal client-side rendering (Angular et.al.) even after the onDomReady event, it still has to render the templates and maybe get some data!
How it works in .Net
In the Node world they can execute the templates (which are simply Javascript) on the server with issues as they are already running a JavaScript engine.
For .NET to run these templates on the server, we’re going to have to run a JavaScript engine too! Don’t worry, this isn’t as bad as you thought! There are two .NET builds specifically for React: the Offical React.Net and Offroadcode’s very own SuperchargedReact.Net.
The official implementation keeps a pool of engines in memory, which could be one of several types (MSIE, Jint, and v8 from clearscript).
SuperchargedReact.Net has a different approach. We only use clearscripts v8 (let’s just agree that v8 is the best) and instead of pooling the engines, it uses a single engine but with several contexts on the same engine. This reduces memory consumption.
How it works in Umbraco
Umbraco very much wants to be in control of the templates, so we use route Hi-jacking to create models which either return rendered HTML through React , or JSON if it’s an AJAX request (such as the client requires more data). I've setup document types which all use the same razor template, this results in razor being in charge of the rendering.
Seeing it in action: A Supercharged demo
I've prepared a demo which includes a compiled bundle of the component. It has been made to be runnable from within Visual Studio. Simply open the solution and then run it.
Compiling
Once you have it running locally, you can (although it isn’t needed) compile the JavaScript yourself. You will need to have React installed and then install the packages, by running “npm install” from the command line. Doing so will install React and the boilerplate components I’ve installed, such as the routing engine.
Next you will need to build the JavaScript into a bundle file. I’ve chosen Webpack for this, you can install by running:
npm install webpack -g
This will install globally, you may need to reopen your console after this, then it’s a simple case of running “webpack -- watch” and your javascript files will be compiled into the bundle when changes are detected.
NPM is package manager that is similar to .NET’s NuGet. It comes installed when you install NodeJs. You’ll find the following NPM commands useful:
npm install – this will install all the which are required by the project
npm install <packagename> --save will install a package as a dependency and save it to the package manifest file.
React Structure
The entry point into our JavaScript is in the file ~/Assets/JS/app.jsx. This file is where the application is kicked off from, it’s here we load our routes into Javascript (which are stored in ~/Assets/JS/routes.jsx) also initiate our Article store.
Article Listing
For the listing page, we have two components: a list and a list item these are stored in ~/Assets/JS/components/ArticleFolder.jsx. Some React occurs in the ArticleItem component on the link to a specific article. This <Link> element is built into the router system which I’ve installed, and this module will introduce an <a> element into the DOM, so even if the client hasn’t got JavaScript enabled the link will cause a standard request to the server, meaning the site will degrade gracefully.
Once the Article component is loaded, it will render once with the data which has from the article store, and it will make a request to the server for the complete data for the rest of the article. Once the store has this complete data, it re-renders the page and replaces what’s changed with the updates.
Recap
The flow of a React request looks like this:
- Umbraco matches url to content
- Umbraco Route hijacking does the logic to get the view model
- Umbraco renders the React Serverside Template with the viewmodel
- React kicks off on the server and renders the template
- React’s rendered HTML and the viewmodel are sent in the response HTML
- React is started on the client and verifies the displayed HTML.
Conclusion
I would use React on a large site where there are lots of interactions that go on with the user, but not on a smaller site as the benefits of Isomorphic rendering wouldn't substantial enough to overcome the larger development costs.