How to Build a Routing Layer in React and Why You Need It

Semaphore
5 min readJul 18, 2023

--

In a single-page React Application, routing refers to the process of navigating between different pages without triggering a full page reload. The application initially loads a single HTML page. Then, it dynamically renders different components based on user interaction.

Since React does not have built-in routing capabilities, you need to implement it using a third-party library. Each library is different, but what usually happens is that you end up spreading the routing logic throughout your React application.

Now, imagine adding a layer to your architecture that encapsulates what is required to route between pages in React. Having the routing logic in one place would bring several benefits to your architecture and make your codebase more maintainable. Not bad, eh?

Let’s now understand what a routing layer is and learn how to implement it in React.

What is a routing layer?

A routing layer is the part of a frontend React application responsible for managing paths and rendering the appropriate page components. When a user clicks on a link or enters a URL in the address bar, the routing layer intercepts the request and determines which component or view should be rendered based on the current path.

In particular, a basic routing layer in React consists of a basic react-router-domsetup and the following two elements:

  • PathConstants: An object that contains all page routes.
const PathConstants = {
TEAM: "/team",
REPORT_ANALYSIS: "reports/:reportId/analysis",
// ...
}
  • routes: An array that includes the mappings between a route string and the page components.
const routes = [
{ path: PathConstants.TEAM, element: <TeamPage /> },
{ path: PathConstants.REPORT_ANALYSIS, element: <ReportAnalysisPage /> },
// ...
]

To register a new route, you only have to add a new constant to PathConstantsand associate it with a page component in routes. Also, all links to that page should use the string path defined in PathConstants:

<a href={PathConstants.TEAM}>Go to the team page!</a>

In other words, you just centralized most of the routing logic of your React app in just a couple of files. This is what a routing layer is all about!

Let’s now dig into the benefits that such an approach to routing brings to your React architecture.

Why your react app should have a routing layer

There are many reasons why you should adopt a routing layer in a frontend architecture. In detail, it allows you to:

  • Centralize routing logic: in a routing layer, all route mapping logic is centralized in a few files. Specifically, this means that you can place all the custom loaders, actions, fetchers introduced in react-router-dom v6.4 in it.
  • Enhance performance: instead of loading all page components at the beginning, you can configure React to lazily load them only when required. This mechanism is called code-splitting and leads to better performance when a user navigates through a React app. To enable it, you need to use lazy imports on page components. With a routing layer, all page imports are in the same file. Thus, controlling the code-splitting feature becomes easier.
  • Improve maintainability: thanks to a routing layer, you can specify all the route mappings in the same place. Now, if a page needs to change its route, you only have to update one constant defined in the routing layer. Without this, you would have to look for all route string references and manually update them.

These are all good reasons why your React app should have a routing layer. Keep reading and see how to add it to your frontend React architecture.

Implement a routing layer in a React app with React Router DOM

Follow this step-by-step tutorial and learn how to build a routing layer in React.

Prerequisites

Handling routing in an SPA application in React becomes easier with the right library. Here, you will look at how to implement a routing layer with react-router-dom, the most popular library that provides client-side routing capabilities to React apps. Keep in mind that you can achieve a similar result with any other routing library.

You can add react-router-dom to your project’s dependencies with the command below:

npm install react-router-dom

To follow this guide, you will need version 6.4 or higher. If your project relies on an older version of the library, you can follow the official migration guide to upgrade it.

Setting up client routing with React Router DOM

First, you need to add a router to your React app. The most popular one offered by React Router DOM is a browser router, which relies on the DOM History API to manage the page URL and update the history stack. Create one withcreateBrowserRouter()function by updating App.js, as follows:

// ./App.js
import {
createBrowserRouter,
RouterProvider,
} from "react-router-dom"
import Home from "./pages/Home"
// ...
import About from "./pages/About"
function App() {
// initialize a browser router
const router = createBrowserRouter([
{
path: "/",
element: <Home />,
},
// other pages....
{
path: "/about",
element: <About />,
},
])
return (
<RouterProvider router={router} />
)
}
export default App

This is what a basic setup of React Router DOM looks like. When you now visit the"/" and "/about" pages, react-router-dom will load the <Home> and <About>components, respectively. In general, whenever you click on a <Link> component, React Router will mount a specific page as defined in the router object.

In a real-world scenario, your web app in React is likely to follow a layout. For example, it might have a header, footer, and/or side menu. Right now, react-router-dom re-renders the entire page when you click on a link. Ideally, it should only reload the content area of the template.

To achieve that, you can define a Layout component as follows:

// ./src/components/Layout.js
import { Outlet } from "react-router-dom"
import Header from "./Header"
import Footer from "./Footer"
export default function Layout() {
return (
<>
<Header />
<main>
<Outlet />
</main>
<Footer />
</>
)
}

Do not forget that this is just an example of a custom <Layout> component. Yours might look different. What you need to focus your attention on is the special <Outlet> component from react-router-dom. This allows a parent route element to render its child route elements. In other words, it will be replaced by child page components.

You can update App.js to render child routes in <Layout>, as shown below:

// ./App.js
import {
createBrowserRouter,
RouterProvider,
} from "react-router-dom"
import Layout from "./components/page"
import Home from "./pages/Home"
// ...
import About from "./pages/About"
function App() {
const router = createBrowserRouter([
{
// parent route component
element: <Layout />,
// child route components
children: [
{
path: "/",
element: <Home />,
},
// other pages....
{
path: "/about",
element: <About />,
},
],
},
])
return (
<RouterProvider router={router} />
)
}
export default App

<Home> and <About> will now be mounted in the <Outlet /> section of <Layout>.

Note that the createBrowserRouter() parent element can also accept an errorElement component. That will be rendered when no path matches the specified URL. You can use it like in the following snippet:

const router = createBrowserRouter([
{
element: <Layout />,
// your custom routing error component
errorElement: <Page404 />,
children: [
// ...
],
},
])

Great! React Router DOM has been set up correctly!

As you can see, the length and complexity of the router object grow as the number of pages increases. Time to address this problem with a React routing layer!

Read the entire article here: https://semaphoreci.com . Published on July 18, 2023.

--

--

Semaphore
Semaphore

Written by Semaphore

Supporting developers with insights and tutorials on delivering good software. · https://semaphoreci.com

No responses yet