React Router

React Router is a powerful library for managing navigation and routing in React applications. It enables developers to create single-page applications with dynamic routing, allowing users to navigate between different views without reloading the page. In this chapter, we'll cover everything from the basics to advanced concepts of React Router.

What is React Router?

React Router is a standard library for routing in React. It enables the navigation between views of various components in a React Application, allows changing the browser URL, and keeps the UI in sync with the URL.

Why Use React Router?

  • SPA Navigation: It provides seamless navigation for single-page applications (SPAs) without reloading the entire page.
  • Dynamic Routing: Routes can be dynamically added and removed.
  • URL Management: Simplifies the management of URLs and their corresponding components.
  • Nested Routes: Supports nested routing for complex applications.
  • Declarative: Routes are defined declaratively, making the code more readable and maintainable.

Basic Concepts of React Router

Let’s start with the basic concepts and setup of React Router in a React application.

Installation

To use React Router, you need to install the react-router-dom package:

				
					npm install react-router-dom

				
			

Setting Up React Router

To set up React Router, you need to wrap your application in the BrowserRouter component and define some basic routes.

				
					// App.js
import React from 'react';
import { BrowserRouter as Router, Route, Switch, Link } from 'react-router-dom';

const Home = () => <h2>Home</h2>;
const About = () => <h2>About</h2>;
const Contact = () => <h2>Contact</h2>;

const App = () => {
  return (
    <Router>
      <div>
        <nav>
          <ul>
            <li>
              <Link to="/">Home</Link>
            </li>
            <li>
              <Link to="/about">About</Link>
            </li>
            <li>
              <Link to="/contact">Contact</Link>
            </li>
          </ul>
        </nav>

        <Switch>
          <Route exact path="/" component={Home} />
          <Route path="/about" component={About} />
          <Route path="/contact" component={Contact} />
        </Switch>
      </div>
    </Router>
  );
};

export default App;

				
			

Explanation

  • BrowserRouter: Wraps the entire application and enables routing.
  • Link: Provides navigation to different routes without reloading the page.
  • Switch: Renders the first child <Route> that matches the location.
  • Route: Defines a route with a path and a component to render.

Output

When you run this application, you will see navigation links for “Home”, “About”, and “Contact”. Clicking these links will navigate to the corresponding components without reloading the page

Nested Routes

Nested routes allow you to define routes within other routes. This is useful for creating complex layouts with nested navigation.

Let’s create a blog application with nested routes for individual blog posts.

				
					// App.js
import React from 'react';
import { BrowserRouter as Router, Route, Switch, Link, useRouteMatch } from 'react-router-dom';

const Home = () => <h2>Home</h2>;
const About = () => <h2>About</h2>;

const Blog = () => {
  let { path, url } = useRouteMatch();
  return (
    <div>
      <h2>Blog</h2>
      <ul>
        <li>
          <Link to={`${url}/post1`}>Post 1</Link>
        </li>
        <li>
          <Link to={`${url}/post2`}>Post 2</Link>
        </li>
      </ul>

      <Switch>
        <Route exact path={path}>
          <h3>Please select a post.</h3>
        </Route>
        <Route path={`${path}/:postId`} component={Post} />
      </Switch>
    </div>
  );
};

const Post = ({ match }) => {
  return <h3>Requested Post ID: {match.params.postId}</h3>;
};

const App = () => {
  return (
    <Router>
      <div>
        <nav>
          <ul>
            <li>
              <Link to="/">Home</Link>
            </li>
            <li>
              <Link to="/about">About</Link>
            </li>
            <li>
              <Link to="/blog">Blog</Link>
            </li>
          </ul>
        </nav>

        <Switch>
          <Route exact path="/" component={Home} />
          <Route path="/about" component={About} />
          <Route path="/blog" component={Blog} />
        </Switch>
      </div>
    </Router>
  );
};

export default App;

				
			

Explanation

  • useRouteMatch: A hook that returns the match object for the current route. It provides the current path and url.
  • Nested Routes: Defined within the Blog component, allowing for navigation to individual blog posts.

Output

When you navigate to the “Blog” link, you will see links to “Post 1” and “Post 2”. Clicking these links will display the respective post ID.

URL Parameters and Query Strings

React Router allows you to extract URL parameters and query strings from the route.

URL Parameters

You can define URL parameters in the route path using a colon (:).

				
					const User = ({ match }) => {
  return <h3>User ID: {match.params.userId}</h3>;
};

const App = () => {
  return (
    <Router>
      <div>
        <nav>
          <ul>
            <li>
              <Link to="/">Home</Link>
            </li>
            <li>
              <Link to="/user/1">User 1</Link>
            </li>
            <li>
              <Link to="/user/2">User 2</Link>
            </li>
          </ul>
        </nav>

        <Switch>
          <Route exact path="/" component={Home} />
          <Route path="/user/:userId" component={User} />
        </Switch>
      </div>
    </Router>
  );
};

				
			

Explanation

  • match.params: Contains the parameters from the URL. In this case, userId is extracted from the URL.

Output

When you navigate to “/user/1” or “/user/2”, it will display “User ID: 1” or “User ID: 2”, respectively.

Query Strings

To handle query strings, you can use the useLocation hook from react-router-dom.

				
					import { useLocation } from 'react-router-dom';

const useQuery = () => {
  return new URLSearchParams(useLocation().search);
};

const Search = () => {
  let query = useQuery();
  return <h3>Query: {query.get("q")}</h3>;
};

const App = () => {
  return (
    <Router>
      <div>
        <nav>
          <ul>
            <li>
              <Link to="/">Home</Link>
            </li>
            <li>
              <Link to="/search?q=react">Search React</Link>
            </li>
            <li>
              <Link to="/search?q=router">Search Router</Link>
            </li>
          </ul>
        </nav>

        <Switch>
          <Route exact path="/" component={Home} />
          <Route path="/search" component={Search} />
        </Switch>
      </div>
    </Router>
  );
};

				
			

Explanation

  • useLocation: Returns the location object representing the current URL.
  • URLSearchParams: Parses query strings from the URL.

Output

When you navigate to “/search?q=react” or “/search?q=router”, it will display “Query: react” or “Query: router”, respectively.

Redirects and Programmatic Navigation

React Router provides ways to redirect users and navigate programmatically.

Redirect Component

You can use the Redirect component to navigate to a different route.

				
					import { Redirect } from 'react-router-dom';

const Home = () => <h2>Home</h2>;
const Login = () => <h2>Login</h2>;

const PrivateRoute = ({ component: Component, ...rest }) => {
  const isAuthenticated = false; // Replace with actual authentication logic
  return (
    <Route
      {...rest}
      render={(props) =>
        isAuthenticated ? (
          <Component {...props} />
        ) : (
          <Redirect to="/login" />
        )
      }
    />
  );
};

const App = () => {
  return (
    <Router>
      <div>
        <Switch>
          <Route exact path="/" component={Home} />
          <Route path="/login" component={Login} />
          <PrivateRoute path="/dashboard" component={() => <h2>Dashboard</h2>} />
        </Switch>
      </div>
    </Router>
  );
};

				
			

Explanation

  • PrivateRoute: A custom route component that redirects to the login page if the user is not authenticated.
  • Redirect: Navigates to a specified route.

Output

When you navigate to “/dashboard”, you will be redirected to the “/login” page if not authenticated.

Programmatic Navigation

To navigate programmatically, use the useHistory hook.

				
					import { useHistory } from 'react-router-dom';

const Home = () => {
  let history = useHistory();

  const handleClick = () => {
    history.push("/about");
  };

  return (
    <div>
      <h2>Home</h2>
      <button onClick={handleClick}>Go to About</button>
    </div>
  );
};

const App = () => {
  return (
    <Router>
      <div>
        <Switch>
          <Route exact path="/" component={Home} />
          <Route path="/about" component={() => <h2>About</h2>} />
        </Switch>
      </div>
    </Router>
  );
};

				
			

Explanation

  • useHistory: Provides access to the history instance, allowing navigation to different routes programmatically.

Output

Clicking the “Go to About” button will navigate to the “/about” route.

Advanced Topics

Let’s explore some advanced concepts like route guards, nested dynamic routes, and lazy loading routes.

Route Guards

You can protect routes using custom route guard components.

				
					const PrivateRoute = ({ component: Component, ...rest }) => {
  const isAuthenticated = true; // Replace with actual authentication logic
  return (
    <Route
      {...rest}
      render={(props) =>
        isAuthenticated ? (
          <Component {...props} />
        ) : (
          <Redirect to="/login" />
        )
      }
    />
  );
};

				
			

Nested Dynamic Routes

Dynamic routes can be nested to handle more complex URL structures.

				
					const Topic = ({ match }) => {
  return <h3>Requested Topic ID: {match.params.topicId}</h3>;
};

const Topics = ({ match }) => {
  return (
    <div>
      <h2>Topics</h2>
      <ul>
        <li>
          <Link to={`${match.url}/components`}>Components</Link>
        </li>
        <li>
          <Link to={`${match.url}/props-v-state`}>Props v. State</Link>
        </li>
      </ul>

      <Switch>
        <Route exact path={match.path}>
          <h3>Please select a topic.</h3>
        </Route>
        <Route path={`${match.path}/:topicId`} component={Topic} />
      </Switch>
    </div>
  );
};

const App = () => {
  return (
    <Router>
      <div>
        <Switch>
          <Route exact path="/" component={Home} />
          <Route path="/topics" component={Topics} />
        </Switch>
      </div>
    </Router>
  );
};

				
			

Lazy Loading Routes

For performance optimization, routes can be lazy-loaded using React.lazy and Suspense.

				
					import React, { Suspense, lazy } from 'react';

const Home = lazy(() => import('./Home'));
const About = lazy(() => import('./About'));

const App = () => {
  return (
    <Router>
      <Suspense fallback={<div>Loading...</div>}>
        <Switch>
          <Route exact path="/" component={Home} />
          <Route path="/about" component={About} />
        </Switch>
      </Suspense>
    </Router>
  );
};

				
			

Explanation

  • React.lazy: Dynamically imports a component.
  • Suspense: Wraps components that should be rendered lazily and displays a fallback while loading.

Output

When you navigate to the respective routes, the components will be loaded dynamically, improving the initial load time.

Example 1: Blog Application with Nested Routes

In this example, we’ll build a blog application where users can view a list of blog posts and click on each post to view its details.

Step-by-Step Implementation

Step 1: Create the Blog and Post Components

First, create components for displaying the list of blog posts and individual post details.

				
					// Post.js
import React from 'react';
import { useParams } from 'react-router-dom';

const Post = () => {
    const { postId } = useParams();
    return <h3>Post ID: {postId}</h3>;
};

export default Post;

// Blog.js
import React from 'react';
import { Link, Route, Switch, useRouteMatch } from 'react-router-dom';
import Post from './Post';

const Blog = () => {
    let { path, url } = useRouteMatch();

    return (
        <div>
            <h2>Blog</h2>
            <ul>
                <li>
                    <Link to={`${url}/1`}>Post 1</Link>
                </li>
                <li>
                    <Link to={`${url}/2`}>Post 2</Link>
                </li>
                <li>
                    <Link to={`${url}/3`}>Post 3</Link>
                </li>
            </ul>

            <Switch>
                <Route exact path={path}>
                    <h3>Please select a post.</h3>
                </Route>
                <Route path={`${path}/:postId`} component={Post} />
            </Switch>
        </div>
    );
};

export default Blog;

				
			

Step 2: Create the Home Component

Create a simple Home component.

				
					// Home.js
import React from 'react';

const Home = () => {
    return <h2>Home</h2>;
};

export default Home;

				
			

Step 3: Set Up the App Component

Set up the App component to include routing for the home page and the blog.

				
					// App.js
import React from 'react';
import { BrowserRouter as Router, Route, Switch, Link } from 'react-router-dom';
import Home from './Home';
import Blog from './Blog';

const App = () => {
    return (
        <Router>
            <div>
                <nav>
                    <ul>
                        <li>
                            <Link to="/">Home</Link>
                        </li>
                        <li>
                            <Link to="/blog">Blog</Link>
                        </li>
                    </ul>
                </nav>

                <Switch>
                    <Route exact path="/" component={Home} />
                    <Route path="/blog" component={Blog} />
                </Switch>
            </div>
        </Router>
    );
};

export default App;

				
			

Explanation

  • useParams: Extracts the post ID from the URL.
  • useRouteMatch: Returns the match object, allowing us to construct nested routes.
  • Link: Navigates to different routes without reloading the page.
  • Route: Defines a route with a path and a component to render.
  • Switch: Renders the first matching route.

Output

When you run this application, you will see navigation links for “Home” and “Blog”. Clicking “Blog” will show links to individual blog posts. Clicking a post link will display its details.

Example 2: User Dashboard with Authentication

In this example, we’ll build a user dashboard where users must log in to access protected routes.

Step-by-Step Implementation

Step 1: Create the Login and Dashboard Components

First, create components for the login page and the dashboard.

				
					// Login.js
import React from 'react';
import { useHistory } from 'react-router-dom';

const Login = () => {
    let history = useHistory();

    const handleLogin = () => {
        // Simulate authentication
        localStorage.setItem('auth', 'true');
        history.push('/dashboard');
    };

    return (
        <div>
            <h2>Login</h2>
            <button onClick={handleLogin}>Log In</button>
        </div>
    );
};

export default Login;

// Dashboard.js
import React from 'react';

const Dashboard = () => {
    return <h2>Dashboard</h2>;
};

export default Dashboard;

				
			

Step 2: Create the Home Component

Create a simple Home component.

				
					// Home.js
import React from 'react';

const Home = () => {
    return <h2>Home</h2>;
};

export default Home;

				
			

Step 3: Create a PrivateRoute Component

Create a custom route component that redirects to the login page if the user is not authenticated.

				
					// PrivateRoute.js
import React from 'react';
import { Route, Redirect } from 'react-router-dom';

const PrivateRoute = ({ component: Component, ...rest }) => {
    const isAuthenticated = localStorage.getItem('auth') === 'true';

    return (
        <Route
            {...rest}
            render={(props) =>
                isAuthenticated ? (
                    <Component {...props} />
                ) : (
                    <Redirect to="/login" />
                )
            }
        />
    );
};

export default PrivateRoute;

				
			

Step 4: Set Up the App Component

Set up the App component to include routing for home, login, and the protected dashboard.

				
					// App.js
import React from 'react';
import { BrowserRouter as Router, Route, Switch, Link } from 'react-router-dom';
import Home from './Home';
import Login from './Login';
import Dashboard from './Dashboard';
import PrivateRoute from './PrivateRoute';

const App = () => {
    return (
        <Router>
            <div>
                <nav>
                    <ul>
                        <li>
                            <Link to="/">Home</Link>
                        </li>
                        <li>
                            <Link to="/login">Login</Link>
                        </li>
                        <li>
                            <Link to="/dashboard">Dashboard</Link>
                        </li>
                    </ul>
                </nav>

                <Switch>
                    <Route exact path="/" component={Home} />
                    <Route path="/login" component={Login} />
                    <PrivateRoute path="/dashboard" component={Dashboard} />
                </Switch>
            </div>
        </Router>
    );
};

export default App;

				
			

Explanation

  • useHistory: Provides access to the history instance, allowing navigation to different routes programmatically.
  • localStorage: Stores the authentication status.
  • PrivateRoute: A custom route component that checks if the user is authenticated. If not, it redirects to the login page.

Output

When you run this application, you will see navigation links for “Home”, “Login”, and “Dashboard”. Clicking “Dashboard” will redirect to the login page if not authenticated. After logging in, you will be redirected to the dashboard.

React Router is an essential library for managing navigation and routing in React applications. It allows you to create dynamic and nested routes, manage URL parameters and query strings, and implement redirects and route guards. By understanding and applying the concepts covered in this chapter, you can build complex, user-friendly navigation systems in your React applications. Happy coding !❤️

Table of Contents

Contact here

Copyright © 2025 Diginode

Made with ❤️ in India