Higher-level understanding of server and client-side routing with React Router

Joel Rivera
Sep 24 · 6 min read

If you’ve been programming using React or have thought about using React, there is a high possibility React Router has come up in conversation as a way to handle client-side routing in React.

This post aims to cover higher-level understanding of server and client-side routing, and how React Router might be a great option for you if you’re able to harness its power.


Difference Between Server-Side Routing and Client-Side Routing

Server-side routing

The more common approach to handling routes is server-side routing. Server-side routing is not part of React Router but it is still the most common form of handling routes.

With server-side routing, a user clicks a link that requests a new page or new data from the server (another computer). And then new data or document is served to the user.

Let’s break this down a little more:

When a user clicks on a link on a webpage, another whole page is loaded and rendered onto the screen. The URL path is updated to match where the user is in the current state of the web page.

This “whole page” that is loaded and rendered is done through the server. Server-side routing is what causes the whole page to refresh because we are making another request to our server, which is providing us with a brand new page to display.

In steps:

  1. User clicks on a link on the webpage.

2. The link sends a request to the server (another computer).

3. The server responds with the new content.

4. This content refreshes the information on the user’s screen.

5. The URL is updated to reflect where the user is at on the webpage.

It is the server that is serving up the contents and files for the browser to display for the user.

The main drawback to using server-side routing is the varied time it can take content to display on a page. If the page the user is requesting will still have that header and footer information displayed onto the screen, then why would we need to reload this information?

But the server doesn’t know that we don’t have to reload that information because it’s already being displayed. The server will send back the file that needs to be displayed and then call for a full refresh to get this new file displayed.

With the full refresh, we now bring internet speeds into the equation. Internet speeds contribute to the time it might take for something to be displayed onto the page.

But how can we prevent this complete page refresh and possibly slow down our render time?

Client-side routing

Client-side routing is the internal handling of a route inside of your JS file that is rendered to the front end (or client).

The reason client-side routing has become something more developers have been considering when creating their apps is due to the popularity of creating single-page applications (SPAs).

With an SPA, when a user clicks on an internal link within your application, the goal would be to see a change in the URL bar to show that there is an update happening to the page without a full page refresh.

With an SPA, we don’t require multiple pages to load, just the original request with our initial HTML, CSS, and JS files from the server. Because of this, client-side routing is used to create that SPA experience while making the routes more uniform and organized for our users to see.

The routing is to give our users a better experience overall because they are able to pinpoint with the route in the URL bar where they are at in the application, all without us needing to make multiple server requests.

But why do we care?

We care about client-side routing for a few reasons:

  1. It gives the user a URL that makes more intuitive sense to be able to see where they are currently at in your application.
  2. We want to give the user the ability to use the “back” and “forward” buttons in their browser using the history API.
  3. It gives the user the ability to type in a specific URL and be able to load that specific view in the application.
  4. The application will have less lag time between different links because the information that is needed to render the next view was already loaded after the initial load of the page.

React Router’s Approach to Client-Side Routing

React Router takes a more dynamic rather than static approach to client-side routing. But what is the difference between the two?

Static routes

In short, with static routes, we establish the routes we are looking to hit up front and then call the routes when needed. This would be implemented by probably having a separate JavaScript file, possibly called routes.js that would contain all of the possible routes that your application would need to hit.

Now, every time a user clicks on a link, this will call on that routes.js file you created and look for the endpoint that matches the link that was clicked on.

This creates an extra step after the link is clicked because now the server is called to respond to this request. The problem with this is that these requests take time to be resolved. This new request time can vary depending on the strength of the connection making this call to the server file.

However, if you have used React before, you would quickly come to realize this wouldn’t be the “React way” to do this. To prove this further, in older applications with React, you might have gone as far as having to create your own API with the same functionality as your component life cycle methods.

Dynamic routing

With dynamic routing, routes are updated as your app renders. In other words, the route that is seen in the URL bar is updating for the client to see, however, there is no communication with any server for that to happen.

React Router to its core is a component. This means adding router functionality to your React app is done the same way you would add any other functionality to your React app.

Let’s dive into this example below:

import React from "react";
import ReactDOM from 'react-dom';
// import your BrowserRouter here just like importing any other functionalityimport { BrowserRouter as Router, Route } from 'react-router-dom';const HomePage = () => {
return (
<div>
<h1>Welcome to the Home Page!</h1>
</div>
);
};
// now <Route> is being wrapped around <Router> to have the router coordinate displayed insteadReactDOM.render((
<Router>
<Route path='/' render={HomePage} />
</Router>),
document.getElementById('root')
);

In the above example, we’re importing BrowserRouter into our application and using the <Router> functionality to match the path.

But the true power of dynamic routing with React Router is like this:

import React from "react";
import ReactDOM from 'react-dom';
import { BrowserRouter as Router, Route } from 'react-router-dom';
const HomePage = () => {
return (
<div>
<h1>Welcome to the Home Page!</h1>
</div>
);
};
// Using match to dynamically generate which user is being passedconst User = ({ match }) => {
return (
<div>
<h3>{match.params.userId}</h3>
</div>
);
};
ReactDOM.render((
<Router>
<Route path='/' render={HomePage} />
// the new path will be the user's id passed into the User component
<Route path='/:userId' component={User} />
</Router>),
document.getElementById('root')
);

So what did we just see?

When we match the URL with a UserId, the displayed route for the user is going to be rendered using the match property to now match the specific URL with the ID that is passed to the match.params.userId into the <Route>.

React Router allows us to keep the uniform links while keeping true to the dynamic rendering and routing of React, but like everything else in technology, there are certainly cons to using dynamic routing.

A key con is that the initial request to the homepage can take longer. Since the whole page needs to be loaded on the initial load, this can cause that initial request to the homepage to take longer than it would if all of the app’s contents wouldn’t have to load immediately.

In summary, I think it’s best to know both client and server-side routing and then you can decide which you would prefer to use for your application. Server-side routing is still the standard, but client-side is making a splash for a reason.

Better Programming

Advice for programmers.

Joel Rivera

Written by

I am a software engineer currently specializing in building out scalable applications using React and Node.JS, docker-izing and deploying them on AWS.

Better Programming

Advice for programmers.

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade