Mastering React routing: A guide to routing in React

Published on January 20, 2025

Mastering React routing: A guide to routing in React

React is one of the most popular libraries in modern web development for creating user interfaces (UIs). It provides a set of tools to help developers create interactive and reusable components using a component-based architecture. React focuses on building the UI only, so routing (navigating between different views or pages) is not built into the library and is supplied by additional libraries like React Router.

Routing is essential for creating anything more than basic applications, as it allows users to move between different pages of the app while loading the relevant content for each route.

In this post, you'll learn the fundamentals of React routing, from setting up routes to implementing advanced features like dynamic routes and lazy loading. By the end, you will have the knowledge to implement React routing in your own applications.

React routing explained

Routing is a mechanism that allows users to navigate between different pages or sections of a web application, usually triggered in response to a link or button being clicked in the UI.

Server-side vs. client-side routing in React

There are two different kinds of routing in React, depending on how your application is built and deployed: server side and client side. These approaches exist because of the evolving need to balance performance, interactivity, and user experience.

In server-side routing, each navigation request triggers a full page reload, fetching and rendering a new HTML document from the server. This approach is effective, but can result in slower user experiences due to network latency, full page reload (rather than just the parts that need to be reloaded), and rendering time on the server.

Client-side routing is managed directly in the browser using JavaScript. Instead of reloading the entire page, the browser fetches and renders only the content that needs to be updated. So, the client-side router will simulate a full page reload by deciding which JavaScript components or views to show based on the route provided to it on the front end. This is the foundation of single-page applications (SPAs), which aim to improve user experience by avoiding full page reloads.

As React is a library that is often used to create SPAs, routing in React is typically handled on the client side using libraries such as react-router-dom, which is the most popular React routing library. It offers features such as dynamic routing, nested routes, and query parameter handling. Other alternatives include Reach Router, which is just a lightweight version of React Router, and Next.js, which is designed for server-side rendering (SSR) and hybrid routing.

Diagram comparing server-side routing and React routing with client-side routing.

This tutorial will use react-router-dom, which provides the following key features that are essential to implementing routing in React:

  • Dynamic routes: Routes that are defined using UI components, allowing for flexibility and easy updates.

  • Nested routes: The ability to organize and manage complex routing hierarchies for descriptive URLs and maintainability.

  • Route parameters: Support for dynamic parameters in URLs, for example, supplying the ID of a blog post that should be loaded (/blog/:id).

  • Redirects and guards: Ways to control user access with redirects or route protection based on conditions.

  • Hooks: Built-in function hooks such as useNavigate and useParams, to simplify route handling.

  • Lazy loading: A way to optimize performance by loading components only when needed.

The different types of routers in React routing

The React Router library provides different types of routing to manage navigation. Each router is suited to specific use cases depending on the kind of application you're building. 

Below is an explanation of the different React routing types and when to use them, with a code example for each:

Browser router

When routing in React, the BrowserRouter is the most commonly used router for building web applications. It uses the HTML5 history API to keep the UI in sync with the URL, resulting in clean and user-friendly URLs. Use BrowserRouter if you have a web application hosted on a server capable of handling dynamic routes — which just means your server will be set up to always serve the same index.html file for any route and let React handle the routing entirely on the client side.

Hash router

The HashRouter in React routing uses the hash portion of the URL (e.g. http://example.com/#/about) to manage routing: anything after the hash is not sent to the server, then it uses JavaScript to map the portion after the hash to a component. The hash router is ideal for environments where the server cannot handle dynamic routes, when hosting a static site, or when backward compatibility with older browsers is required.

Memory router

The React Router library's MemoryRouter stores the navigation history in memory rather than syncing it with the browser's URL bar. This routing method doesn't affect or rely on the browser's address bar, making it suitable for building navigation for client-side applications and native apps using tools like React Native to implement React Native routing.

React routing example with react-router-dom

Installing and configuring React Router

If you would prefer to start your own project, to start routing in React, you will first need to install the react-router-dom package:

npm install react-router-dom

Import the necessary components for setup in your App.js or equivalent entry file:

The <Router> component wraps your application and provides the routing context. Both <Routes> and <Route> define the paths and the components to render for each route. You will need to manually edit the URL to switch between routes in this example.

You can find example code here.

React routing with useNavigate

You can use the onClick event trigger in React and the useNavigate hook from React Router to move between the routes/pages of your application:

The above example has two separate components: Home, which is displayed at the default route of the application, and About. Both have a navigation button, which uses the useNavigate hook to allow routing between the two.

You can find example code here.

Fallback routes while routing in React

When a user tries to access a route that doesn't exist, you should tell them (usually in the form of a ”page not found” message with a link back to the home page). In React routing, you can achieve this with a fallback route:

Now, when you try to access a route that doesn't exist, you will see a message "404: Page not found" with a navigation button taking you back to the homepage.

You can find example code here

Key hooks in React routing

Here is a summary of the key hooks you can use in React Router:

Hook

Purpose

Typical use case

useNavigate

Navigate programmatically

Redirect after form submission, etc.

useLocation

Get the current route information

Check the pathname or route state

useParams

Access dynamic route parameters

Retrieve values like /user/:id

useRoutes

Define routes dynamically in components

Configure routes programmatically

useSearchParams

Work with query parameters in the URL

Filter or sort data via queries

Implementing protected routes in React routing


You can use a combination of hooks and components when routing in React to achieve custom functionality. For example, you may want a certain part of your app to be inaccessible until a user logs in. Please note the following is just an example of authentication, and in a real-world scenario, you would need to implement security measures such as token-based authentication:

Above, the authentication status is stored in a boolean variable named isAuthenticated in the application state, which is set to true or false by clicking the login button (this is for example purposes; in a full application you'd actually authenticate the user). The state is passed to the PrivateRoute component, which is wrapping the Dashboard. Depending on the value of the isAuthenticated variable, it either displays the component or navigates the user to the Login component. 

From the PrivateRoute, the Location is passed to the Login component with the useLocation hook, so it knows where the user was trying to get to, and, once they’re logged in, can redirect them to their intended destination. The Link component is also being used, which is an alternative to using a button with an onClick event listener, and the useNavigate hook is a way you can programmatically navigate a user without requiring an interaction from them.

You can find example code here.

Dynamic React routing

Dynamic routing in React allows you to create routes with placeholders that can match dynamic segments in the URL. The useParams hook lets you access this functionality.

In the App component example above, the Link component is used to pass through dynamic blogId variables to the route, and when it routes to the BlogArticle component, the useParams hook is used to extract that blogId and display it in the UI. It could be used for a network call to fetch specific blog information, for example.

You can find example code here.

Implementing lazy loading when routing in React

Lazy loading in React allows you to load components only when they are needed, improving performance by reducing the initial load time of your application. 

The below code shows how to use React.lazy and React.Suspense together with React Router to load the components dynamically only when their respective routes are accessed:

Example code.

SEO considerations when routing in React

Search engine crawlers rely on fully rendered HTML to index pages effectively. Since React handles routing on the client side, it initially serves a minimal HTML file, and the rest of the content is rendered dynamically in the browser. This can result in incomplete or poorly indexed pages if crawlers are unable to execute JavaScript efficiently or if there are delays in rendering. These limitations make SPAs (with client-side routing) difficult to optimize for search engines.

If you are planning on applying SEO to your apps, you should consider using a framework like Next.js, which solves the SEO challenges discussed in the last section by using server-side rendering (SSR) to pre-render pages on the server before they are sent to the browser. This ensures that search engine crawlers receive fully rendered HTML, improving indexing and visibility.

React routing and app frameworks like Next.js

Frameworks like Next.js have simplified routing by providing developers with the ability to create routes based on the file structure without extra configuration, so you can easily build nested routes, fine-tune route behavior with middleware, and add params to your filenames for easy dynamic routing.

Build fast, responsive React apps with Contentful

Using react-router-dom to handle your routing in React with a composable content platform like Contentful can be an effective choice for content-heavy websites, allowing you to compose your back end quickly and manage routing and dynamic content, simply delivering highly personalized experiences to your users worldwide.

Combining routing in React with react-router-dom, and lazy loading features with Contentful's REST and GraphQL APIs, is a powerful way to build fast, responsive, and content-driven applications. By lazy loading routes and components, your app can cut down its initial load time, while Contentful ensures that content is delivered quickly from multiple edge locations via its globally distributed CDN.

You can bootstrap your own React app, already configured for Contentful with our React starter, or use our Next.js starter app, which is optimized for Contentful, including server-side rendering and dynamic content fetching.

Subscribe for updates

Build better digital experiences with Contentful updates direct to your inbox.

Meet the authors

David Fateh

David Fateh

Software Engineer, Contentful

David Fateh is a software engineer with a penchant for web development. He helped build the Contentful App Framework and now works with developers that want to take advantage of it.

Related articles

What's TypeScript? It's a powerful tool for frontend & backend developers. It promotes better code quality and protects against common JavaScript mistakes.
Guides

What is TypeScript and why should you use it?

August 18, 2022

Design tokens are a critical element of every successful design system.
Guides

Design tokens explained (and how to build a design token system)

May 16, 2024

The Next.js app directory (or App Router) overhauls how apps are structured and improves development.
Guides

How to use the Next.js app directory: Complete guide and tutorial

January 17, 2025

Contentful Logo 2.5 Dark

Ready to start building?

Put everything you learned into action. Create and publish your content with Contentful — no credit card required.

Get started