DEV Community

Oliver Kem
Oliver Kem

Posted on

React Router v6

Hello Everyone, React router v6 is out. I have been tinkering with it for a while and I love it. With everything updated and some new hooks to use with your application, I have decided to write this article to share my knowledge on it. Let's begin

Prerequisites

  1. React
  2. Javascript/Typescript

Now, let us begin. We will start by creating our React Application using vite. I will be using pnpm but feel free to use yarn or npm.
Go to your terminal and run the following commands

$ pnpm create vite@latest
Enter fullscreen mode Exit fullscreen mode

Follow the prompts and select Typescript. Install the dependencies and start the app

Installation Screenshot

Now let us start by installing the React router library React Router

$ pnpm add react-router-dom
Enter fullscreen mode Exit fullscreen mode

Let us create a page. Create a folder called pages in scr and called it HomePage.tsx. Then paste the following

function HomePage() {
    return (
        <div>
            <h1>Home Page</h1>
        </div>
    );
}

export default HomePage;
Enter fullscreen mode Exit fullscreen mode

Now, on our App.tsx
We need to write the following

import './App.css'
import { createBrowserRouter,RouterProvider} from "react-router-dom";
import HomePage from "./pages/HomePage";
function App() {
  const router = createBrowserRouter([
    { 
      path: "/",
      element: <HomePage/>
    },
  ]);
  return (
    <RouterProvider router={router}/>
  )
}

export default App
Enter fullscreen mode Exit fullscreen mode

Now when someone visits our http://localhost:5173/ they will be greeted with this page.

Now, in your application. You May have an overall layout comprising a design that your want other pages to wrap around this. Let me show you how we can do it.
Create a folder called components and add a file called layouts.component.tsx

import { OutLet } from `react-router-dom`;
function LayoutsComponent() {
    return (
        <div>
            <h1>This is the overall layout</h1>
            <Outlet/>
        </div>
    );
}

export default LayoutsComponent;
Enter fullscreen mode Exit fullscreen mode

Let us create two pages UsersPage.tsx and ProductsPage.tsx. Now add some dummy data and we import them in our App.tsx
Now with this, we need to wrap our app with this layout.
In our App.tsx page:

import './App.css'
import { createBrowserRouter,RouterProvider} from "react-router-dom";
import HomePage from "./pages/HomePage";
import LayoutsComponent from './components/layouts.component';
import UsersPage from './pages/UsersPage';
import ProductsPage from './pages/ProductsPage';
function App() {
    const router = createBrowserRouter([
        { 
            path: "/",
            element: <HomePage/>,
        },
        {
            element: <LayoutsComponent/>,
            children: [
                {
                path: "/users",
                element: <UsersPage/>,
                },
                {
                path: "/products",
                element: <ProductsPage/>,
                },
            ],
        }
    ]);
    return (
        <RouterProvider router={router}/>
    )
}

export default App

Enter fullscreen mode Exit fullscreen mode

From above, we have just passed the <UsersPage/> and <ProductsPage/> as children to the <LayoutsComponent/> page, now they will wrap inside.

Now, in the Layouts component, you might want to pass data to every child component that might be wrapping inside it. This might come in handy, for example when you are designing for responsive view and you want to pass data to its children to respond a certain way when the layout changes. To do this we will us a special hook called useOutletContext() but before we do this, in the layout.component.tsx let us pass some data to the children.

import { useEffect, useState } from "react";
import { Outlet } from "react-router-dom";
function LayoutsComponent() {
    const [data,setData] = useState([]);
    useEffect(() => {
        fetch('https://jsonplaceholder.typicode.com/users')
        .then(response => response.json())
        .then(json => setData(json))
    },[])
    return (
        <div>
            <h1>This is the overall layout</h1>
            <Outlet context={[data]} />
        </div>
    );
}

export default LayoutsComponent;
Enter fullscreen mode Exit fullscreen mode

From our example, we have just updated our application import and now the data will be used my the children here.
Now to consume the data in our children(UsersPage):

import { useOutletContext } from "react-router-dom";
function UsersPage() {
    // eslint-disable-next-line @typescript-eslint/no-unused-vars
    const [ data  ]= useOutletContext<[string[]]>();
    return (
        <div>
            <h1>Users Page</h1>
            <ul>
                {data.map((item,index) => (
                    <li key={index}>{item}</li>
                ))}
            </ul>
        </div>
    );
}

export default UsersPage;
Enter fullscreen mode Exit fullscreen mode

Now let us spice things up. You may want to introduce a loader, such that before we view a user information, before we view navigate to the user's profile page. To do this we write the following

{
    path: "/users",
        element: <UsersPage/>,
    children: [
            {
                 path: ":id",
                 element: <UserProfile/>,
                 loader: async ({ params }) => {
                const response = await fetch(`https://jsonplaceholder.typicode.com/users/${params.id}`);
                const data = await response.json();
                return data;
                  }
            },
       ],
},
Enter fullscreen mode Exit fullscreen mode

From this, you can choose to display the user data information

import { useLoaderData } from "react-router-dom";
function UserProfile() {
    const data= useLoaderData();

    return (
        <div>
            <h1>User Profile</h1>
            <p>{data}</p>
        </div>
    );
}

export default UserProfile;
Enter fullscreen mode Exit fullscreen mode

Feel free to check the original documentation Docs

Top comments (0)