Backend routing

In the preceding example, you implemented a single request handler in the server that responded to requests for the root URL (/). Your application is going to need to handle more than a single route. You learned how to use the react-router package for routing in the previous chapter. Now, you're going to see how to use the same package in Node.js.

First, let's take a look at the main App component:

import React from 'react';
import { Route, Link } from 'react-router-dom';

import FirstHeader from './first/FirstHeader';
import FirstContent from './first/FirstContent';
import SecondHeader from './second/SecondHeader';
import SecondContent from './second/SecondContent';

export default () => (
<section>
<header>
<Route exact path="/" render={() => <h1>App</h1>} />
<Route exact path="/first" component={FirstHeader} />
<Route exact path="/second" component={SecondHeader} />
</header>
<main>
<Route
exact
path="/"
render={() => (
<ul>
<li>
<Link to="first">First</Link>
</li>
<li>
<Link to="second">Second</Link>
</li>
</ul>
)}
/>
<Route exact path="/first" component={FirstContent} />
<Route exact path="/second" component={SecondContent} />
</main>
</section>
);

There are three routes that this application handles:

  • /: The home page
  • /first: The first page of content
  • /second: The second page of content

The App content is divided into <header> and <main> elements. In each of these sections, there is a <Route> component that handles the appropriate content. For example, the main content for the / route is handled by a render() function that renders links to /first and /second.

This component will work fine on the client, but will it work on the server? Let's implement that now:

import React from 'react';
import { renderToString } from 'react-dom/server';
import { StaticRouter } from 'react-router';
import express from 'express';

import App from './App';

const app = express();

app.get('/*', (req, res) => {
const context = {};
const html = renderToString(
<StaticRouter location={req.url} context={context}>
<App />
</StaticRouter>
);

if (context.url) {
res.writeHead(301, {
Location: context.url
});
res.end();
} else {
res.write(`
<!doctype html>
<div id="app">${html}</div>
`);
res.end();
}
});

app.listen(8080, () => {
console.log('Listening on 127.0.0.1:8080');
});

You now have both frontend and backend routing! How does this work exactly? Let's start with the request handler path. This has changed this so that it's now a wildcard (/*). Now this handler is called for every request.

On the server, the <StaticRouter> component is used instead of the <BrowserRouter> component. The <App> component is the child, which means that the <Route> components within will be passed data from <StaticRouter>. This is how <App> knows to render the correct content based on the URL.  The resulting html value that results from calling renderToString() can then be used as part of the document that's sent to the browser as a response.

Now your application is starting to look like a real end-to-end React rendering solution. This is what the server renders if you hit the root URL /:

If you hit the /second URL, the Node.js server will render the correct component:

If you navigate from the main page to the first page, the request goes back to the server. We need to figure out how to get the frontend code to the browser so that it can take over after the initial render.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.145.108.9