React Router v6
Tags: react, reactrouter, typescript, vite
Published: 2023-06-16 13:55:24

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](https://vitejs.dev). 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
```
Follow the prompts and select Typescript. Install the dependencies and start the app

![Installation Screenshot](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2kjl8l3uxis2auuv4ywy.png)

Now let us start by installing the React router library [React Router](https://reactrouter.com/en/main)
```
$ pnpm add react-router-dom
```
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;
```
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
```
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;
```
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

```

> 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;
```
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;
```
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;
			      }
			},
       ],
},
```

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;
```
Feel free to check the original documentation [Docs](https://reactrouter.com/en/main/start/overview)