A practical guide to React Router v6

Adel Benyahia
4 min readOct 29, 2022

In this practical tutorial, we will learn how to implement protected Routes in ReactJS using React Higher-Order component and react router <Outlet>

  1. What is React Higher-Order component
  2. What is React Router
  3. What react Router used for
  4. What is React router <Outlet>
  5. Let's start coding
  6. The Complete project source code on codesandbox.io

1. What is React Higher-Order component

A higher-order component (HOC) is an advanced technique in React for reusing component logic. HOCs are not part of the React API, per se. They are a pattern that emerges from React’s compositional nature.

Example:

const EnhancedComponent = higherOrderComponent(WrappedComponent);

2. What is React Router?

React Router is a fully-featured client and server-side routing library for React, a JavaScript library for building user interfaces. React Router runs anywhere React runs; on the web, on the server with node.js, and on React Native.

3. What React Router used for?

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

At the time of writing this tutorial, the react-router-dom is in version 6.

We will start from this project Simple styled login form with ReactJS

Its a simple ReactJs with a login form

We will start our project from this point.

4. What is React router <Outlet>

An <Outlet> should be used in parent route elements to render their child route elements. This allows nested UI to show up when child routes are rendered. If the parent route matched exactly, it will render a child index route or nothing if there is no index route.

Example:

function Dashboard() {
return (
<div>
<h1>Dashboard</h1>
      {/* This element will render either <DashboardMessages> when the URL is
"/messages", <DashboardTasks> at "/tasks", or null if it is "/"
*/}
<Outlet />
</div>
);
}
function App() {
return (
<Routes>
<Route path="/" element={<Dashboard />}>
<Route
path="messages"
element={<DashboardMessages />}
/>
<Route path="tasks" element={<DashboardTasks />} />
</Route>
</Routes>
);
}

5. Let’s start coding

First install react-router package

npm install react-router-dom

or

yarn add react-router-dom

Then in

index.js

import { StrictMode } from "react";import { createRoot } from "react-dom/client";import { BrowserRouter, Route, Routes } from "react-router-dom";import App from "./App";
const rootElement = document.getElementById("root");const root = createRoot(rootElement);root.render(<StrictMode> <BrowserRouter> <Routes> <Route path="/*" element={<App />} /> </Routes> </BrowserRouter></StrictMode>);

. <BrowserRouter> is the parent component that is used to store all of the other components, it must wrap all component that use Routes

. <Routes> they act like a switch between different <Route > in react router

. <Route> are perhaps the most important part of a React Router app. They couple URL segments to components, data loading and data mutations. Through route nesting …

App.js

import "./styles.css";import { useEffect, useState } from "react";import Login from "./Login";import { Routes, Route } from "react-router-dom";import Home from "./Home";import Dash from "./Dash";import Profile from "./Profile";import PageNotFound from "./PageNotFound";export default function App() {return (<Routes>  {/* Routes */}  <Route index element={<Home />} />  <Route path="login" element={<Login />} />  {/*Nested Routes using Outlet*/}  <Route path="dash" element={<Dash />}>    <Route index element={<Dash />} />    <Route path=":user" element={<Profile user="USER" />} />  </Route>  {/* 404 page */}  <Route path="*" element={<PageNotFound />} /></Routes>
);
}

In this file

<Route index element={<Home />} />

We have “index” with means when we are on “/” or “/index” or “/index.html” route to the element: <Home>

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

We have path=”login”, when we are on the path “/login” the application will show the <Login> component.

<Route path="*" element={<PageNotFound />} />

When the value of path=”*” the application will route unknown path the <PageNotFound> component, its a 404 page.

The most tricky part of code is this

{/*Nested Routes using Outlet*/}<Route path="dash" element={<Dash />}>  <Route index element={<Dash />} />  <Route path=":user" element={<Profile user="USER" />} /></Route>

I will explain

the <Dash> component act like a container for <Profile> component,

If you put “user123” in the <Login> username input and click the button login, it will navigate to “/dash/user123”

const handleSubmit = async (e) => {  e.preventDefault();  navigate(`/dash/${username}`);};

in <Dash> component it will render the

<h1>Dash</h1>

then render the<Outlet> with is the children of the nested Route, in our case the <Profile> component.

In our <Profile> component we will get the “username” params using the React Router hook “useParams”

const {user} ) useParams()

And out put it

return <p>Welcome {user}</p>;

The <Dash> component

import { Outlet } from "react-router-dom";export default function Dash() {return (<>  <h1>Dash</h1>  <Outlet /></>);}

The <Profile> component

import { useParams } from "react-router-dom";export default function Profile() { const { user } = useParams(); return <p>Welcome {user}</p>;}

Like in this Capture

7. The Complete project source code on codesandbox.io

--

--

Adel Benyahia

Web application developer (HTML │ CSS │ JS | ReactJS | NextJS | NestJS | MERN)