In contrast React is barely more than the V in MVC. That makes it very simple to integrate into existing projects without revamping lots of code. You can easily try React for a particular feature, leaving the rest of your application code alone.
I'm working with React for a few month now in a traditional single-page-application. The application relies on server-side markup rendering and jQuery. Let me describe to you a few techniques I'm using to integrate React in a non-invasive way.
Let's assume we're working on an existing single-page-application with a static HTML5 layout consisting of some general elements like a header, footer, sidebar and a content container, holding the actual HTML of each individual page:
For every internal application link we call an appriopriate controller on the server which renders the page. We could use a simple routing function to handle the ajax calls to the server and then replace the html of the main content container with the server-rendered markup. Before the actual html will be replaced, we trigger a custom jQuery event
content-will-change, who's purpose will be revealed later in this article.
Instead of rendering the full HTML page on the server with an arbitrary template engine, we now want to utilize React.js to render the html in the browser for a particular page. The tricky part is how to integrate client-side react rendering without changing too much existing code like the routing function described above.
Normally you would implement a REST controller on the server and let the client handle all the rendering and routing between views. But since most parts of our existing application still rely on server-side rendering we would need to completely rewrite the routing function.
Instead we just retain server-side rendering for the React view, but instead of rendering the whole html on the server we just render an empty container and the json data into a minimal html skeleton, so the client can do the rest of the work. Putting all the json data directly into the skeleton view saves us from performing additional ajax calls later on when rendering the react components on the client.
In a Java webapp we could utilize
ObjectMapper from the Jackson library to transform arbitrary Java objects into json strings. For example if we want to render a react component showing a list of books, we use the method
writeValueAsString() to transform the list of books into valid json:
The server controller now returns the html skeleton consisting of an empty books container and a script block to render the react component into this container passing the dehydrated json data as a parameter to the render function:
When the routing function replaces the html on the site via
$('#content').html(html) this script block gets evaluated, forcing React to render the component into the books container:
The above code is written in EcmaScript 6 (aka ES2015) + JSX syntax. Although not all browsers support ES6 as of today, you can safely use ES6 in production by transpiling the code into valid ES5 with Babel.js. Babel also compiles Reacts JSX syntax which makes it the perfect tool for React development.
As you might already have noticed in the above code I don't use
React.render to render the
<BookList/> component. Instead I'm using a utility wrapper called
ReactContentRenderer. The purpose of this module is to automatically unmount all react components rendered into the content container before loading a new page. This is critical in traditional single-page-applications to prevent memory leaks since React keeps references to all mounted components until they get unmounted from the DOM.
ReactContentRenderer keeps a reference to all component nodes and listens on
content-will-change events to unmount those components before the html of the content container gets replaced via
If you don't unmount those components, React would never know that the underlying HTML does no longer exist. You can inspect all mounted components by using the React Dev Tools (browser extension) to manually assure that obsolete components are already unmounted.
I hope you've enjoyed this article. Don't hesitate to share your feedback with me on Twitter or use the comments below. You might also be interested in reading my article about how to render React components on Java servers by utilizing the Java 8 Nashorn engine. You should also check out my React Samples repository on GitHub, containing a bunch of client-side React examples.