React Router is the de facto normal routing library for React. When that you must navigate by means of a React software with a number of views, you’ll want a router to handle the URLs. React Router takes care of that, retaining your software UI and the URL in sync.

This tutorial introduces you to React Router v6 and an entire lot of issues you are able to do with it.

Desk of Contents

Introduction

React is a well-liked JavaScript library for constructing interactive internet functions that may ship dynamic content material. Such functions might need a number of views (aka pages), however in contrast to standard multi-page apps, navigating by means of these views shouldn’t end in your entire web page being reloaded. As a substitute, views are rendered inline throughout the present web page.

The top person, who’s accustomed to multi-page apps, expects the next options to be current:

  • Every view ought to have a URL that uniquely specifies that view. That is in order that the person can bookmark the URL for reference at a later time — for instance, www.instance.com/merchandise.
  • The browser’s again and ahead button ought to work as anticipated.
  • Dynamically generated nested views ought to ideally have a URL of their very own too — comparable to instance.com/merchandise/sneakers/101, the place 101 is the product ID.

Routing is the method of retaining the browser URL in sync with what’s being rendered on the web page. React Router allows you to deal with routing declaratively. The declarative routing strategy permits you to management the info circulation in your software, by saying “the route ought to seem like this”:

<Route path="/about" aspect={<About />} />

You possibly can place your <Route> element anyplace you need your path to be rendered. Since <Route>, <Hyperlink> and all the opposite APIs that we’ll be coping with are simply parts, you’ll be able to simply stand up and operating with routing in React.

Word: there’s a standard false impression that React Router is an official routing answer developed by Fb. In actuality, it’s a third-party library that’s developed and maintained by Remix Software program.

Overview

This tutorial is split into totally different sections. First, we’ll arrange React and React Router utilizing npm. Then we’ll leap proper into some fundamentals. You’ll discover totally different code demonstrations of React Router in motion. The examples coated on this tutorial embody:

  • primary navigational routing
  • nested routing
  • nested routing with path parameters
  • protected routing

All of the ideas related with constructing these routes can be mentioned alongside the best way.

Your entire code for the mission is out there on this GitHub repo.

Let’s get began!

Establishing React Router

To comply with together with this tutorial, you’ll want a latest model of Node put in in your PC. If this isn’t the case, then head over to the Node dwelling web page and download the correct binaries for your system. Alternatively, you may think about using a model supervisor to put in Node. We now have a tutorial on using a version manager here.

Node comes bundled with npm, a package deal supervisor for JavaScript, with which we’re going to put in among the libraries we’ll be utilizing. You possibly can learn more about using npm here.

You possibly can examine that each are put in accurately by issuing the next instructions from the command line:

node -v
> 20.9.0

npm -v
> 10.1.0

With that completed, let’s begin off by creating a brand new React mission with the Create React App software. You possibly can both set up this globally, or use npx, like so:

npx create-react-app react-router-demo

When this has completed, become the newly created listing:

cd react-router-demo

The library contains three packages: react-router, react-router-dom, and react-router-native. The core package deal for the router is react-router, whereas the opposite two are atmosphere particular. It is best to use react-router-dom when you’re constructing an online software, and react-router-native when you’re in a cell app growth atmosphere utilizing React Native.

Use npm to put in react-router-dom package deal:

npm set up react-router-dom

Then begin the event server with this:

npm run begin

Congratulations! You now have a working React app with React Router put in. You possibly can view the app operating at http://localhost:3000/.

React Router Fundamentals

Now let’s familiarize ourselves with a primary setup. To do that, we’ll make an app with three separate views: House, Class and Merchandise.

The Router Part

The very first thing we’ll have to do is to wrap our <App> element in a <Router> element (supplied by React Router). There are several kinds of router available, however in our case, there are two which advantage consideration:

The first distinction between them is obvious within the URLs they create:


https://instance.com/about


https://instance.com/#/about

The <BrowserRouter> is usually used because it leverages the HTML5 History API to synchronize your UI with the URL, providing a cleaner URL construction with out hash fragments. Alternatively, the <HashRouter> makes use of the hash portion of the URL (window.location.hash) to handle routing, which could be useful in environments the place server configuration isn’t attainable or when supporting legacy browsers missing HTML5 Historical past API assist. You possibly can read more about the differences here.

Word additionally that 4 new routers, which assist varied new data APIs, had been launched in a latest model of React Router (v6.4). On this tutorial, we’ll give attention to the standard routers, as they’re strong, nicely documented and utilized in a myriad of initiatives throughout the web. We’ll, nevertheless, dive into what’s new in v6.4 in a later part.

So, let’s import the <BrowserRouter> element and wrap it across the <App> element. Change index.js to seem like this:



import React from 'react';
import ReactDOM from 'react-dom/shopper';
import App from './App';
import { BrowserRouter } from 'react-router-dom';

const root = ReactDOM.createRoot(doc.getElementById('root'));
root.render(
  <React.StrictMode>
    <BrowserRouter>
      <App />
    </BrowserRouter>
  </React.StrictMode>
);

This code creates a historical past occasion for our total <App> element. Let’s have a look at what which means.

A Little Little bit of Historical past

The historical past library allows you to simply handle session historical past anyplace JavaScript runs. A historical past object abstracts away the variations in varied environments and offers a minimal API that allows you to handle the historical past stack, navigate, and persist state between periods. — remix-run

Every <Router> element creates a historical past object that retains monitor of the present and former places in a stack. When the present location modifications, the view is re-rendered and also you get a way of navigation.

How does the present location change? In React Router v6, the useNavigate hook offers a navigate perform that can be utilized for this objective. The navigate perform is invoked if you click on on a <Hyperlink> element, and it can be used to switch the present location by passing an choices object with a substitute: true property.

Different strategies — comparable to navigate(-1) for going again and navigate(1) for going ahead — are used to navigate by means of the historical past stack by going again or ahead a web page.

Apps don’t have to create their very own historical past objects; this activity is managed by the <Router> element. In a nutshell, it creates a historical past object, subscribes to modifications within the stack, and modifies its state when the URL modifications. This triggers a re-render of the app, guaranteeing the suitable UI is displayed.

Shifting on, we now have Hyperlinks and Routes.

Hyperlink and Route Elements

The <Route> element is a very powerful element in React Router. It renders some UI if the situation matches the present route path. Ideally, a <Route> element ought to have a prop named path, and if the trail title matches the present location, it will get rendered.

The <Hyperlink> element, however, is used to navigate between pages. It’s similar to the HTML anchor aspect. Nevertheless, utilizing anchor hyperlinks would end in a full web page refresh, which we don’t need. So as a substitute, we are able to use <Hyperlink> to navigate to a specific URL and have the view re-rendered with no refresh.

Now we’ve coated every little thing that you must make our app work. Delete all recordsdata aside from index.js and App.js from the mission’s src folder, then replace App.js as follows:

import { Hyperlink, Route, Routes } from 'react-router-dom';

const House = () => (
  <div>
    <h2>House</h2>
    <p>Welcome to our homepage!</p>
  </div>
);

const Classes = () => (
  <div>
    <h2>Classes</h2>
    <p>Browse gadgets by class.</p>
  </div>
);

const Merchandise = () => (
  <div>
    <h2>Merchandise</h2>
    <p>Browse particular person merchandise.</p>
  </div>
);

export default perform App() {
  return (
    <div>
      <nav>
        <ul>
          <li>
            <Hyperlink to="/">House</Hyperlink>
          </li>
          <li>
            <Hyperlink to="/classes">Classes</Hyperlink>
          </li>
          <li>
            <Hyperlink to="/merchandise">Merchandise</Hyperlink>
          </li>
        </ul>
      </nav>

      <Routes>
        <Route path="/" aspect={<House />} />
        <Route path="/classes" aspect={<Classes />} />
        <Route path="/merchandise" aspect={<Merchandise />} />
      </Routes>
    </div>
  );
}

Right here, we’ve declared three parts — <House>, <Classes>, and <Merchandise> — which signify totally different pages in our software. The <Routes> and <Route> parts imported from React Router are utilized to outline the routing logic.

Within the <App> element we now have a primary navigation menu, the place every merchandise is a <Hyperlink> element from React Router. The <Hyperlink> parts are used to create navigable hyperlinks to totally different elements of the appliance, every related to a particular path (/, /classes and /merchandise respectively). Word that in a bigger app, this menu might be encapsulated inside a format element to keep up a constant construction throughout totally different views. You may also wish to add some sort of energetic class (comparable to utilizing a NavLink component) to the at the moment chosen nav merchandise. Nevertheless, to maintain issues focussed, we’ll skip this right here.

Beneath the navigation menu, the <Routes> element is used as a container for a set of particular person <Route> parts. Every <Route> element is related to a particular path and a React element to render when the trail matches the present URL. For instance, when the URL is /classes, the <Classes> element is rendered.

Word: in earlier variations of React Router, / would match each / and /classes, that means that each parts had been rendered. The answer to this is able to have been to move the actual prop to the <Route>, guaranteeing that solely the precise path was matched. This conduct modified in v6, in order that now all paths match precisely by default. As we’ll see within the subsequent part, if you wish to match extra of the URL as a result of you may have little one routes, use a trailing * — comparable to <Route path="classes/*" ...>.

In case you’re following alongside, earlier than continuing, take a second to click on across the app and ensure every little thing behaves as anticipated.

Nested Routing

Prime-level routes are all nicely and good, however earlier than lengthy most functions will want to have the ability to nest routes — for instance, to show a specific product, or to edit a particular person.

In React Router v6, routes are nested by putting <Route> parts inside different <Route> parts within the JSX code. This manner, the nested <Route> parts naturally mirror the nested construction of the URLs they signify.

Let’s have a look at how we are able to implement this in our app. Change App.js, like so (the place ... signifies that the earlier code stays unchanged):

import { Hyperlink, Route, Routes } from 'react-router-dom';
import { Classes, Desktops, Laptops } from './Classes';

const House = () => ( ... );
const Merchandise = () => ( ... );

export default perform App() {
  return (
    <div>
      <nav>...</nav>

      <Routes>
        <Route path="/" aspect={<House />} />
        <Route path="/classes/" aspect={<Classes />}>
          <Route path="desktops" aspect={<Desktops />} />
          <Route path="laptops" aspect={<Laptops />} />
        </Route>
        <Route path="/merchandise" aspect={<Merchandise />} />
      </Routes>
    </div>
  );
}

As you’ll be able to see, we’ve moved the <Classes> element into its personal web page and are actually importing two additional parts, particularly <Desktops> and <Laptops>.

We’ve additionally made some modifications to the <Routes> element, which we’ll have a look at in a second.

First, create a Classes.js file in the identical folder as your App.js file. Then add the next code:


import { Hyperlink, Outlet } from 'react-router-dom';

export const Classes = () => (
  <div>
    <h2>Classes</h2>
    <p>Browse gadgets by class.</p>
    <nav>
      <ul>
        <li>
          <Hyperlink to="desktops">Desktops</Hyperlink>
        </li>
        <li>
          <Hyperlink to="laptops">Laptops</Hyperlink>
        </li>
      </ul>
    </nav>

    <Outlet />
  </div>
);

export const Desktops = () => <h3>Desktop PC Web page</h3>;
export const Laptops = () => <h3>Laptops Web page</h3>;

Refresh your app (this could occur routinely if the dev server is operating) after which click on on the Classes hyperlink. It is best to now see two new menu factors (Desktops and Laptops) and clicking on both one will show a brand new web page inside the unique Classes web page.

So what did we simply do?

In App.js we modified our /classes path to seem like this:

<Route path="/classes/" aspect={<Classes />}>
  <Route path="desktops" aspect={<Desktops />} />
  <Route path="laptops" aspect={<Laptops />} />
</Route>

Within the up to date code, the <Route> element for /classes has been modified to incorporate two nested <Route> parts inside it — one for /classes/desktops and one other for /classes/laptops. This variation illustrates how React Router permits for composability with its routing configuration.

By nesting <Route> parts throughout the /classes <Route>, we’re in a position to create a extra structured URL and UI hierarchy. This manner, when a person navigates to /classes/desktops or /classes/laptops, the respective <Desktops> or <Laptops> element can be rendered throughout the <Classes> element, showcasing a transparent mum or dad–little one relationship between the routes and parts.

Word: the trail of a nested route is routinely composed by concatenating the paths of its ancestors with its personal path.

We’ve additionally altered our <Classes> element to incorporate an <Outlet />:

export const Classes = () => (
  <div>
    <h2>Classes</h2>
    ...
    <Outlet />
  </div>
);

An <Outlet> is positioned in mum or dad route parts to render their little one route parts. This enables nested UI to indicate up when little one routes are rendered.

This compositional strategy makes the routing configuration extra declarative and simpler to know, aligning nicely with React’s component-based structure.

Accessing Router Properties with Hooks

In earlier variations, sure props had been handed implicitly to a element. For instance:

const House = (props) => {
  console.log(props);
  return ( <h2>House</h2> );
};

The code above would log the next:

{
  historical past: { ... },
  location: { ... },
  match: { ... }
}

In React Router model 6, the strategy to passing router props has shifted to offer a extra specific and hook-based technique. The router props historical past, location, and match are not handed implicitly to a element. As a substitute, a set of hooks are supplied to entry this data.

For example, to entry the location object, you’d use the useLocation hook. The useMatch hook returns match information a couple of route on the given path. The historical past object is not explicitly surfaced, fairly the useNavigate hook will return a perform that allows you to navigate programmatically.

There are a lot of extra hooks to discover and fairly than record all of them right here, I might encourage you to take a look at the official documentation, the place out there hooks could be discovered within the sidebar on the left.

Subsequent, let’s have a look at a kind of hooks in additional element and make our earlier instance extra dynamic.

Nested Dynamic Routing

To begin with, change the routes in App.js, like so:

<Routes>
  <Route path="/" aspect={<House />} />
  <Route path="/classes/" aspect={<Classes />}>
    <Route path="desktops" aspect={<Desktops />} />
    <Route path="laptops" aspect={<Laptops />} />
  </Route>
  <Route path="/merchandise/*" aspect={<Merchandise />} />
</Routes>

The eagle-eyed amongst you’ll spot that there’s now a trailing /* on the /merchandise route. In React Router model 6, the /* is a method to point out that the <Merchandise> element can have little one routes, and it’s a placeholder for any further path segments which may comply with /merchandise within the URL. This manner, if you navigate to a URL like /merchandise/laptops, the <Merchandise> element will nonetheless be matched and rendered, and will probably be in a position to additional course of the laptops a part of the trail utilizing its personal nested <Route> parts.

Subsequent, let’s transfer the <Merchandise> element into its personal file:


...
import Merchandise from './Merchandise';

const House = () => ( ... );

export default perform App() { ... }

Lastly, create a Merchandise.js file and add the next code:


import { Route, Routes, Hyperlink, useParams } from 'react-router-dom';

const Merchandise = () => {
  const { title } = useParams();

  return (
    <div>
      <h3>{title}</h3>
      <p>Product particulars for the {title}</p>
    </div>
  );
};

const Merchandise = () => (
  <div>
    <h2>Merchandise</h2>
    <p>Browse particular person merchandise.</p>
    <nav>
      <ul>
        <li>
          <Hyperlink to="dell-optiplex-3900">Dell OptiPlex 3090</Hyperlink>
        </li>
        <li>
          <Hyperlink to="lenovo-thinkpad-x1">Lenovo ThinkPad X1</Hyperlink>
        </li>
      </ul>
    </nav>

    <Routes>
      <Route path=":title" aspect={<Merchandise />} />
    </Routes>
  </div>
);

export default Merchandise;

Right here we’ve added a <Route> to an <Merchandise> element (declared on the high of the web page). The route’s path is ready to :title, which can match any path phase following its mum or dad route and move that phase as a parameter named title to the <Merchandise> element.

Within the <Merchandise> element, we’re utilizing the useParams hook. This returns an object of key/worth pairs of the dynamic params from the present URL. If we had been to log it to the console for the route /merchandise/laptops, we might see:

Object { "*": "laptops", title: "laptops" }

We will then use object destructuring to seize this parameter immediately, after which render it inside an <h3> tag.

Attempt it out! As you’ll see, the <Merchandise> element catches any hyperlinks you declare in your nav bar and creates a web page dynamically.

You can too attempt including some extra menu gadgets:

<li>
  <Hyperlink to="cyberpowerpc-gamer-xtreme">CyberPowerPC Gamer Xtreme</Hyperlink>
</li>

Our app will take these new pages under consideration.

This technique of capturing dynamic segments of the URL and utilizing them as parameters inside our parts permits for extra versatile routing and element rendering based mostly on the URL construction.

Let’s construct on this within the subsequent part.

Nested Routing with Path Parameters

In a real-world app, a router should cope with information and show it dynamically. Let’s assume we now have some product information returned by an API within the following format:

const productData = [
  {
    id: 1,
    name: "Dell OptiPlex 3090",
    description:
      "The Dell OptiPlex 3090 is a compact desktop PC that offers versatile features to meet your business needs.",
    status: "Available",
  },
  {
    id: 2,
    name: "Lenovo ThinkPad X1 Carbon",
    description:
      "Designed with a sleek and durable build, the Lenovo ThinkPad X1 Carbon is a high-performance laptop ideal for on-the-go professionals.",
    status: "Out of Stock",
  },
  {
    id: 3,
    name: "CyberPowerPC Gamer Xtreme",
    description:
      "The CyberPowerPC Gamer Xtreme is a high-performance gaming desktop with powerful processing and graphics capabilities for a seamless gaming experience.",
    status: "Available",
  },
  {
    id: 4,
    name: "Apple MacBook Air",
    description:
      "The Apple MacBook Air is a lightweight and compact laptop with a high-resolution Retina display and powerful processing capabilities.",
    status: "Out of Stock",
  },
];

Let’s additionally assume that we’d like routes for the next paths:

  • /merchandise: this could show a listing of merchandise.
  • /merchandise/:productId: if a product with the :productId exists, it ought to show the product information, and if not, it ought to show an error message.

Change the present contents of Merchandise.js with the next (ensuring to repeat within the product information from above):

import { Hyperlink, Route, Routes } from "react-router-dom";
import Product from "./Product";

const productData = [ ... ];

const Merchandise = () => {
  const linkList = productData.map((product) => {
    return (
      <li key={product.id}>
        <Hyperlink to={`${product.id}`}>{product.title}</Hyperlink>
      </li>
    );
  });

  return (
    <div>
      <h3>Merchandise</h3>
      <p>Browse particular person merchandise.</p>
      <ul>{linkList}</ul>

      <Routes>
        <Route path=":productId" aspect={<Product information={productData} />} />
        <Route index aspect={<p>Please choose a product.</p>} />
      </Routes>
    </div>
  );
};

export default Merchandise;

Contained in the element, we construct a listing of <Hyperlink> parts utilizing the id property from every of our merchandise. We retailer this in a linkList variable, earlier than rendering it out to the web page.

Subsequent come two <Route> parts. The primary has a path prop with the worth :productId, which (as we noticed beforehand) is a route parameter. This enables us to seize and use the worth from the URL at this phase as productId. The aspect prop of this <Route> element is ready to render a <Product> element, passing it the productData array as a prop. Each time the URL matches the sample, this <Product> element can be rendered, with the respective productId captured from the URL.

The second <Route> element makes use of an index prop to render the textual content “Please choose a product” every time the URL matches the bottom path precisely. The index prop signifies that this route is the bottom or “index” route inside this <Routes> setup. So, when the URL matches the bottom path — that’s, /merchandise — this message can be displayed.

Now, right here’s the code for the <Product> element we referenced above. You’ll have to create this file at src/Product.js:

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

const Product = ({ information }) => {
  const { productId } = useParams();
  const product = information.discover((p) => p.id === Quantity(productId));

  return (
    <div>
      {product ? (
        <div>
          <h3> {product.title} </h3>
          <p>{product.description}</p>
          <hr />
          <h4>{product.standing}</h4>
        </div>
      ) : (
        <h2>Sorry. Product does not exist.</h2>
      )}
    </div>
  );
};

export default Product;

Right here we’re making use of the useParams hook to entry the dynamic elements of the URL path as key/worth pairs. Once more, we’re utilizing destructuring to seize the info we’re focused on (the productId).

The discover technique is getting used on the information array to seek for and return the primary aspect whose id property matches the productId retrieved from the URL parameters.

Now if you go to the appliance within the browser and choose Merchandise, you’ll see a submenu rendered, which in flip shows the product information.

Earlier than shifting on, have a mess around with the demo. Guarantee your self that every little thing works and that you simply perceive what’s occurring within the code.

Defending Routes

A standard requirement for a lot of fashionable internet apps is to make sure that solely logged-in customers can entry sure elements of the positioning. On this subsequent part, we’ll have a look at implement a protected route, in order that if somebody tries to entry /admin, they’ll be required to log in.

Nevertheless, there are a few facets of React Router that we have to cowl first.

In model 6, programmatically redirecting to a brand new location is achieved by means of the useNavigate hook. This hook offers a perform that can be utilized to programmatically navigate to a special route. It will possibly settle for an object as a second parameter, used to specify varied choices. For instance:

const navigate = useNavigate();
navigate('/login', {
  state: { from: location },
  substitute: true
});

This may redirect the person to /login, passing alongside a location worth to retailer in historical past state, which we are able to then entry on the vacation spot route by way of a useLocation hook. Specifying substitute: true may even substitute the present entry within the historical past stack fairly than including a brand new one. This mimics the conduct of the now defunct <Redirect> element in v5.

To summarize: if somebody tries to entry the /admin route whereas logged out, they’ll be redirected to the /login route. The details about the present location is handed by way of the state prop, in order that if the authentication is profitable, the person could be redirected again to the web page they had been initially attempting to entry.

Customized Routes

The following factor we have to have a look at are customized routes. A customized route in React Router is a user-defined element that permits for extra performance or behaviors in the course of the routing course of. It will possibly encapsulate particular routing logic, comparable to authentication checks, and render totally different parts or carry out actions based mostly on sure circumstances.

Create a brand new file PrivateRoute.js within the src listing and add the next content material:

import { useEffect } from 'react';
import { useNavigate, useLocation } from 'react-router-dom';
import { fakeAuth } from './Login';

const PrivateRoute = ({ kids }) => {
  const navigate = useNavigate();
  const location = useLocation();

  useEffect(() => {
    if (!fakeAuth.isAuthenticated) {
      navigate('/login', {
        state: { from: location },
        substitute: true,
      });
    }
  }, [navigate, location]);

  return fakeAuth.isAuthenticated ? kids : null;
};

export default PrivateRoute;

There are a number of issues occurring right here. To begin with, we import one thing known as fakeAuth, which exposes an isAuthenticated property. We’ll have a look at this in additional element quickly, however for now it’s adequate to know that that is what we’ll use to find out the person’s logged-in standing.

The element accepts a kids prop. This would be the protected content material that the <PrivateRoute> element is wrapped round when it’s known as. For instance:

<PrivateRoute>
  <Admin /> <-- kids
</PrivateRoute>

Within the element physique, the useNavigate and useLocation hooks are used to acquire the navigate perform and the present location object respectively. If the person isn’t authenticated, as checked by !fakeAuth.isAuthenticated, the navigate perform known as to redirect the person to the /login route, as described within the earlier part.

The element’s return assertion checks the authentication standing once more. If the person is authenticated, its little one parts are rendered. If the person isn’t authenticated, null is returned, rendering nothing.

Word additionally that we’re wrapping the decision to navigate in React’s useEffect hook. It is because the navigate perform shouldn’t be known as immediately contained in the element physique, because it causes a state replace throughout rendering. Wrapping it inside a useEffect hook ensures that it’s known as after the element is rendered.

Necessary Safety Discover

In a real-world app, that you must validate any request for a protected useful resource in your server. Let me say that once more…

In a real-world app, that you must validate any request for a protected useful resource in your server.

It is because something that runs on the shopper can doubtlessly be reverse engineered and tampered with. For instance, within the above code one can simply open React’s dev instruments and alter the worth of isAuthenticated to true, thus having access to the protected space.

Authentication in a React app is worthy of a tutorial of its personal, however one method to implement it could be utilizing JSON Web Tokens. For instance, you can have an endpoint in your server which accepts a username and password mixture. When it receives these (by way of Ajax), it checks to see if the credentials are legitimate. In that case, it responds with a JWT, which the React app saves (for instance, in sessionStorage), and if not, it sends a 401 Unauthorized response again to the shopper.

Assuming a profitable login, the shopper would then ship the JWT as a header together with any request for a protected useful resource. This may then be validated by the server earlier than it despatched a response.

When storing passwords, the server wouldn’t retailer them in plaintext. Moderately, it could encrypt them — for instance, utilizing bcryptjs.

Implementing the Protected Route

Now let’s implement our protected route. Alter App.js like so:

import { Hyperlink, Route, Routes } from 'react-router-dom';
import { Classes, Desktops, Laptops } from './Classes';
import Merchandise from './Merchandise';
import Login from './Login';
import PrivateRoute from './PrivateRoute';

const House = () => (
  <div>
    <h2>House</h2>
    <p>Welcome to our homepage!</p>
  </div>
);

const Admin = () => (
  <div>
    <h2>Welcome admin!</h2>
  </div>
);

export default perform App() {
  return (
    <div>
      <nav>
        <ul>
          <li>
            <Hyperlink to="/">House</Hyperlink>
          </li>
          <li>
            <Hyperlink to="/classes">Classes</Hyperlink>
          </li>
          <li>
            <Hyperlink to="/merchandise">Merchandise</Hyperlink>
          </li>
          <li>
            <Hyperlink to="/admin">Admin space</Hyperlink>
          </li>
        </ul>
      </nav>

      <Routes>
        <Route path="/" aspect={<House />} />
        <Route path="/classes/" aspect={<Classes />}>
          <Route path="desktops" aspect={<Desktops />} />
          <Route path="laptops" aspect={<Laptops />} />
        </Route>
        <Route path="/merchandise/*" aspect={<Merchandise />} />
        <Route path="/login" aspect={<Login />} />
        <Route
          path="/admin"
          aspect={
            <PrivateRoute>
              <Admin />
            </PrivateRoute>
          }
        />
      </Routes>
    </div>
  );
}

As you’ll be able to see, we’ve added an <Admin> element to the highest of the file, and we’re together with our <PrivateRoute> throughout the <Routes> element. As talked about beforehand, this tradition route renders the <Admin> element if the person is logged in. In any other case, the person is redirected to /login.

Lastly, create Login.js and add the next code:



import { useState, useEffect } from 'react';
import { useNavigate, useLocation } from 'react-router-dom';

export default perform Login() {
  const navigate = useNavigate();
  const { state } = useLocation();
  const from = state?.from || { pathname: '/' };
  const [redirectToReferrer, setRedirectToReferrer] = useState(false);

  const login = () => {
    fakeAuth.authenticate(() => {
      setRedirectToReferrer(true);
    });
  };

  useEffect(() => {
    if (redirectToReferrer) {
      navigate(from.pathname, { substitute: true });
    }
  }, [redirectToReferrer, navigate, from.pathname]);

  return (
    <div>
      <p>You need to log in to view the web page at {from.pathname}</p>
      <button onClick={login}>Log in</button>
    </div>
  );
}


export const fakeAuth = {
  isAuthenticated: false,
  authenticate(cb) {
    this.isAuthenticated = true;
    setTimeout(cb, 100);
  },
};

Within the code above, we’re trying to get a price for the URL the person was attempting to entry earlier than being requested to log in. If this isn’t current, we set it to { pathname: "/" }.

We then use React’s useState hook to initialize a redirectToReferrer property to false. Relying on the worth of this property, the person is both redirected to the place they had been going (that’s, the person is logged in), or the person is offered with a button to log them in.

As soon as the button is clicked, the fakeAuth.authenticate technique is executed, which units fakeAuth.isAuthenticated to true and (in a callback perform) updates the worth of redirectToReferrer to true. This causes the element to re-render and the person to be redirected.

Working Demo

Let’s match the puzzle items collectively, we could? Right here’s the ultimate demo of the appliance we constructed utilizing React router.

React Router Model 6.4

Earlier than we end up, we must always point out the discharge of React Router v6.4. Regardless of wanting like an not easily seen level launch, this model launched some groundbreaking new options. For instance, it now consists of the info loading and mutation APIs from Remix, which introduce an entire new paradigm for retaining the UI in sync along with your information.

As of model 6.4, you’ll be able to outline a loader perform for every route, which is chargeable for fetching the info wanted for that route. Inside your element, you utilize the useLoaderData hook to entry the info that was loaded by your loader perform. When a person navigates to a route, React Router routinely calls the related loader perform, fetches the info, and passes the info to the element by way of the useLoaderData hook, with no useEffect in sight. This promotes a sample the place information fetching is tied on to routing.

There’s additionally a brand new <Kind> element which prevents the browser from sending the request to the server and sends it to your route’s motion as a substitute. React Router then routinely revalidates the info on the web page after the motion finishes, which suggests all your useLoaderData hooks replace and the UI stays in sync along with your information routinely.

To make use of these new APIS, you’ll want to make use of the brand new <RouterProvider /> element. This takes a router prop which is created utilizing the brand new createBrowserRouter perform.

Discussing all of those modifications intimately is exterior the scope of this text, however when you’re eager to search out out extra, I might encourage you to comply with together with the official React Router tutorial.

Abstract

As you’ve seen on this article, React Router is a robust library that enhances React for constructing higher, declarative routing in your React apps. On the time of writing, the present model of React Router is v6.18 and the library has undergone substantial change since v5. That is partially as a result of affect of Remix, a full-stack internet framework written by the identical authors.

On this tutorial, we realized:

  • arrange and set up React Router
  • the fundamentals of routing and a few important parts comparable to <Routes>, <Route> and <Hyperlink>
  • create a minimal router for navigation and nested routes
  • construct dynamic routes with path parameters
  • work with React Router’s hooks and its newer route rendering sample

Lastly, we realized some superior routing strategies whereas creating the ultimate demo for protected routes.

FAQs

How Does Routing Work in React Router v6?

This model introduces a brand new routing syntax utilizing the <Routes> and <Route> parts. The <Routes> element wraps round particular person <Route> parts, which specify the trail and the aspect to render when the trail matches the URL.

How Do I Arrange Nested Routes?

Nested routes are created by putting <Route> parts inside different <Route> parts within the JSX code. This manner, the nested <Route> parts naturally mirror the nested construction of the URLs they signify.

How Do I Redirect Customers to One other Web page?

You need to use the useNavigate hook to programmatically navigate customers to a different web page. For example, const navigate = useNavigate(); after which navigate('/path'); to redirect to the specified path.

How Do I Move Props to Elements?

In v6, you’ll be able to move props to parts by together with them within the aspect prop of a <Route> element, like so: <Route path="/path" aspect={<Part prop={worth} />} />.

How Do I Entry Url Parameters in React Router v6?

URL parameters could be accessed utilizing the useParams hook. For instance, if the route is outlined as <Route path=":id" aspect={<Part />} />, you should utilize const { id } = useParams(); to entry the id parameter inside <Part />.

What’s New in React Router v6.4?

Model 6.4 introduces many new options impressed by Remix, such information loaders and createBrowserRouter, aiming to enhance information fetching and submission. Yow will discover an exhaustive record of latest options here.

How Do I Migrate from React Router v5 to v6?

Migrating includes updating your route configurations to the brand new <Routes> and <Route> parts syntax, updating hooks and different API strategies to their v6 counterparts, and addressing any breaking modifications in your software’s routing logic. Yow will discover an official information here.