Server-side rendering in React.js

Server-side rendering in React.js


React offers an approach to render components to strings specifically for the case of server-side rendering.

That is accomplished by the react-dom package, that manages the React to Dom conversion.
However, we don’t need to simply render a view, however the correct view.

That’s where isomorphic or Universal routing comes into the picture.

Server-side rendering in React.js

A normal React application executes in the browser, rendering pages in the DOM in response to user actions.

In order to improve the user experience, we want to render the pages server-side and send the generated static content to the client-side, this will ensure that our content is crawlable by search engines and also allow users with feature phones to consume our content.

Rendering a view

The fundamental concept is that we wrap the app in a stateless <StaticRouter> instead of a <BrowserRouter>. The primary difference between these two routers is that the location of the static router never changes, therefore helpful for our case, where we only have to compute the needed route and send the view back to the client.

let’s look at the client.js file.

// --- client.js

import React from 'react'
import { render } from 'react-dom'
import { BrowserRouter } from 'react-router-dom'

import App from './modules/App'

render((
 
 
 
), document.getElementById('app'));

In the code snippet above the client BrowserRouter stays the same and the server static router handles the incoming requests routing.

import path from 'path';
import React from 'react'
import express from 'express'
// we'll use this to render our app to an HTML string
import { renderToString } from 'react-dom/server'
// and these to match the url to routes and then render
import { StaticRouter } from 'react-router'
import App from './modules/App'

const app = express();

// serve our static stuff
app.use(express.static(path.join(__dirname, 'public')));

app.get('*', (req, res) => {
 const context = {}
 const markup = renderToString()
 res.set('content-type', 'text/html');
 res.send(renderPage(html));
});
function renderPage(appHtml) {
 return`Isomorphic Router Example
 ${appHtml}`
}

In the code snippet above, we are mapping all requests through the app.get to React’s renderToString method from the react-dom package sent back to the client.

The talked about component markup shall be passed to a simple function that generates an HTML with the markup in it. And that is what Express will send back to the client.

A Real-life case of Server-side rendering in React.js

Suppose a user wants to navigate to a protected URL or want to access some private information. In these cases, we use it like this:

// ...
app.get('*', (req, res) => {
 const context = {}
 const markup = renderToString()
 
 if (context.url) {
 // Somewhere a `` was rendered
 res.redirect(302, context.url);
 } else {
 res.set('content-type', 'text/html');
 // here you can use whatever view rendering technique that you like
 res.send(renderPage(html));
 }
});

In the Code Snippet Above, Whenever you render on the client, the browser history changes the state and we get a brand new screen.
In a static server environment, we are able to change the app state. Instead, we use the context prop to search out what the results of rendering were.

If we discover a context.url then we all know the app redirected. This permits us to send a correct redirect from the server. This redirect will make the router handle the following request as if nothing occurred.

Conclusion

In this article we saw how to send the right view to the client, depending on the requested URL, even redirecting to the right URL if needed. the most common use case for server-side rendering is to handle the initial render when a user first requests our app.

So, what about the initial state of the app? Yes, there is a lot more to cover in React server rendering, hopefully, we will cover those in coming articles.


Share on social media

//