SoFunction
Updated on 2025-04-07

Methods to add authentication using React Router v6

React Router v6 is a popular and powerful routing library for React applications. It provides aDeclarative, component-based routing method,andAble to handle common tasks such as URL parameters, redirection and loading data

This latest version of React Router introduces many new concepts, such as<Outlet />andlayoutLayout routes, but there is still little related documentation.

This article will demonstrate how to use itReact Router v6Create protected routes and how to add authentication.

start

Open the terminal and run the following command to create a new React project:

> npx create-react-app ReactRouterAuthDemo
> cd ReactRouterAuthDemo

Next, install it in the React applicationReact RouterAs a dependency:

> npm install react-router-dom

Once the React Router dependencies are installed, we can start editingsrc/document.

First, fromreact-router-domImport inBrowserRouterComponents, then use<BrowserRouter />pack<App />Components, like this:

import { StrictMode } from "react";
import { createRoot } from "react-dom/client";
import { BrowserRouter } from "react-router-dom";
import App from "./App";
const rootElement = ("root");
const root = createRoot(rootElement);

(
  <StrictMode>
    <BrowserRouter>
      <App />
    </BrowserRouter>
  </StrictMode>
);

Basic routing

React Router provides<Routes />and<Route />Components, which enables us to render them according to the current location of the components.

import { Routes, Route } from "react-router-dom";
import { LoginPage } from "./pages/Login";
import { HomePage } from "./pages/Home";
import "./";

export default function App() {
  return (
    <Routes>
      <Route path="/" element={<HomePage />} />
      <Route path="/login" element={<LoginPage />} />
    </Routes>
  );
}

<Route />Provides a mapping of paths between the application and React components. For example, when the user navigates to/loginWhen renderingLoginPageComponents, we just need to provide them like this<Route />:

<Route path="/login" element={<LoginPage />} />

<Route />The component can be regarded as aifStatement, only when the element matches the specified path, it will act onURLlocation.

<Routes />The component isReact Router v5 In-house<Switch />Component alternative.

We can createandCome to use<Routes />

// 
export const LoginPage = () => (
  <div>
    <h1>This is the Login Page</h1>
  </div>
);

// 
export const HomePage = () => (
  <div>
    <h1>This is the Home Page</h1>
  </div>
);

Next, we will run the following command to start the application:

> npm run start

In the browser, we will see by defaultHomeComponents. If we use/loginRouting, we will seeLoginPageThe component is rendered on the screen.

Alternatively, we can also use a normal JavaScript object, throughuseRoutesHook to represent routes in the application. This is a functional method to define routing, and its working method is< routes />and<Route />The components are the same.

import { useRoutes } from "react-router-dom";
// ...

export default function App() {
  const routes = useRoutes([
    {
      path: "/",
      element: <HomePage />
    },
    {
      path: "/login",
      element: <LoginPage />
    }
  ]);
  return routes;
}

Now that the basic setup is complete, let's see how to create a protected route so that unauthenticated users cannot access certain content in the application.

Create protected routes

Before creating a protected route, let's create a custom hook that will useContext APIanduseContextThe hook handles the status of the authenticated user.

import { createContext, useContext, useMemo } from "react";
import { useNavigate } from "react-router-dom";
import { useLocalStorage } from "./useLocalStorage";
const AuthContext = createContext();

export const AuthProvider = ({ children }) =&gt; {
  const [user, setUser] = useLocalStorage("user", null);
  const navigate = useNavigate();

  // When verifying user permissions, access this function  const login = async (data) =&gt; {
    setUser(data);
    navigate("/profile");
  };

  // Sign out  const logout = () =&gt; {
    setUser(null);
    navigate("/", { replace: true });
  };

  const value = useMemo(
    () =&gt; ({
      user,
      login,
      logout
    }),
    [user]
  );
  return &lt; value={value}&gt;{children}&lt;/&gt;;
};

export const useAuth = () =&gt; {
  return useContext(AuthContext);
};

The aboveuseAuthIn the hook, we expose the user's status and some methods for user login and logout. When the user logs out, we useReact RouterofuseNavigateHook to bring themRedirectGo to the home page.

To keep the user's status while the page is refreshed, we will useuseLocalStorageHook, which will synchronize the status values ​​in the browser's local storage.

import { useState } from "react";

export const useLocalStorage = (keyName, defaultValue) => {
  const [storedValue, setStoredValue] = useState(() => {
    try {
      const value = (keyName);
      if (value) {
        return (value);
      } else {
        (keyName, (defaultValue));
        return defaultValue;
      }
    } catch (err) {
      return defaultValue;
    }
  });
  const setValue = (newValue) => {
    try {
      (keyName, (newValue));
    } catch (err) {}
    setStoredValue(newValue);
  };
  return [storedValue, setValue];
};

<ProtectedRoute />The component will be fromuseAuthCheck the status of the current user in the hook, if the user is not authenticated, redirect to/path.

import { Navigate } from "react-router-dom";
import { useAuth } from "../hooks/useAuth";

export const ProtectedRoute = ({ children }) => {
  const { user } = useAuth();
  if (!user) {
    // user is not authenticated
    return <Navigate to="/" />;
  }
  return children;
};

To redirect users, we use<Navigate />Components. When the parent component renders the current location,<Navigate />The component changes the current position. It is used internallyusenavatehook.

existIn the file, we can use<ProtectedRoute />Component packagingpageComponents. For example, we use<ProtectedRoute />Package<SettingsPage />and<ProfilePage />Components. Now, when an unauthenticated user tries to access/profileor/settingsWhen paths are made, they will be redirected to the home page.

import { Routes, Route } from "react-router-dom";
import { LoginPage } from "./pages/Login";
import { HomePage } from "./pages/Home";
import { SignUpPage } from "./pages/SignUp";
import { ProfilePage } from "./pages/Profile";
import { SettingsPage } from "./pages/Settings";
import { ProtectedRoute } from "./components/ProtectedRoute";
export default function App() {
  return (
    <Routes>
      <Route path="/" element={<HomePage />} />
      <Route path="/login" element={<LoginPage />} />
      <Route path="/register" element={<SignUpPage />} />
      <Route
        path="/profile"
        element={
          <ProtectedRoute>
            <ProfilePage />
          </ProtectedRoute>
        }
      />
      <Route
        path="/settings"
        element={
          <ProtectedRoute>
            <SettingsPage />
          </ProtectedRoute>
        }
      />
    </Routes>
  );
}

The above method works well if the number of protected routes is limited, but if there are multiple such routes, we have to wrap each one, which is cumbersome.

Instead, we can use React Router v6'sNested routing featuresEncapsulate all protected routes in one layout.

Using nested routing and <Outlet />

React Router v6One of the most powerful features is nested routing. This feature allows us to have aRouters containing other subroutines. Most of our layouts are coupled to fragments on the URL, and React Router fully supports this.

For example, we can<HomePage />and<LoginPage />Add a parent component to the route<Route />, like this:

import { ProtectedLayout } from "./components/ProtectedLayout";
import { HomeLayout } from "./components/HomeLayout";
// ...

export default function App() {
  return (
    <Routes>
      <Route element={<HomeLayout />}>
        <Route path="/" element={<HomePage />} />
        <Route path="/login" element={<LoginPage />} />
      </Route>

      <Route path="/dashboard" element={<ProtectedLayout />}>
        <Route path="profile" element={<ProfilePage />} />
        <Route path="settings" element={<SettingsPage />} />
      </Route>
    </Routes>
  );
}

Parent component<Route />There can also be a path that is responsible for rendering child components on the screen<Route />

When the user navigates to/dashboard/profileWhen the router will render<ProfilePage />. To achieve this, the parent route element must have a<Outlet />Component to render child elements.OutletComponents make nested UI visible when rendering subroutines.

The parent routing element may also have additional public business logic and user interface. For example,<ProtectedLayout />In the component, we already include the private routing logic and a general navigation bar that will be visible when the subroutine is rendered.

import { Navigate, Outlet } from "react-router-dom";
import { useAuth } from "../hooks/useAuth";

export const ProtectedLayout = () => {
  const { user } = useAuth();

  if (!user) {
    return <Navigate to="/" />;
  }

  return (
    <div>
      <nav>
        <Link to="/settings">Settings</Link>
        <Link to="/profile">Profile</Link>
      </nav>
      <Outlet />
    </div>
  )
};

Apart from<Outlet />Components, we can also choose to useuseOutletHook, its function is the same:

import { Link, Navigate, useOutlet } from "react-router-dom";
// ...
export const ProtectedLayout = () => {
  const { user } = useAuth();
  const outlet = useOutlet();

  if (!user) {
    return <Navigate to="/" />;
  }

  return (
    <div>
      <nav>
        <Link to="/settings">Settings</Link>
        <Link to="/profile">Profile</Link>
      </nav>
      {outlet}
    </div>
  );
};

Similar to protected routes, we do not want authenticated users to access/loginpath. Let's be<HomeLayout />Process it in the component:

import { Navigate, Outlet } from "react-router-dom";
import { useAuth } from "../hooks/useAuth";
export const HomeLayout = () => {
  const { user } = useAuth();

  if (user) {
    return <Navigate to="/dashboard/profile" />;
  }

  return (
    <div>
      <nav>
        <Link to="/">Home</Link>
        <Link to="/login">Login</Link>
      </nav>
      <Outlet />
    </div>
  )
};

Ending

It's worth taking some time to better understand how React Router v6 works, especially user authentication.

React Router v6 is a huge improvement compared to previous versions. It is fast, stable and reliable. Besides being easier to use, it has many new features, such as<Outlets />and an improved<Route />Components, this greatly simplifies routing in React applications.

I hope this guide helps you and hope you have a better understanding of how to handle user authentication using React Router v6.

This is the article about using React Router v6 for authentication. This is all about this article. For more relevant React Router v6 verification content, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!