Routing, Client Side
Tags: webdev, javascript, react, programming
Published: 2024-04-18 01:56:27

Client side routing is a programming method that lets us use custom urls and a browser's history functions to navigate through a single page application. To accomplish this I've learned to use React Router, which gives us the ability to route different url extensions to separate components in our app, and display them only when the user is on that "page".

Remember to install react-router-dom first!
```
>npm install react-router-dom
```

After successfully installing react-router-dom into our repository, we must import it into our app, then import the functions that we need from it.
```
import ReactDOM from 'react-dom/client'
import { createBrowserRouter, RouterProvider } from "react-router-dom"
```

Next we create our router object using the imported function.
```
const router = createBrowserRouter([
  {
    path: "/",
    element: <Home/>
  }
]);
```

We then create a ReactDOM root and assign the application's root to it. We then have this root render our application through the imported RouterProvider component, passing our router object as a prop.
```
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
  <RouterProvider router={router} />);
)
```

After setting all of this up, our application should be running and we're ready to start routing!
```
import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import Home './Home';

import { createBrowserRouter, RouterProvider } from "react-router-dom";

const router = createBrowserRouter([
  {
    path: "/",
    element: <Home />
  }
]);

const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
  <RouterProvider router={router} />);
)
```

Once that's all set up, the only thing we need to do to add a new route is add the path and corresponding element to our router object.

```
const router = createBrowserRouter([
  {
    path: "/",
    element: <Home />
  },
  {
    path: "/donate",
    element: <DonationForm />
  }
]);
```

One could navigate to either /home or /donate now by typing the extensions into their browser, but if we want to make this a little more user friendly we'll have to add links. NavLinks are a special component that will navigate to the given url extension. 
```
function NavBar() {
  return (
    <div className="NavBar">
        <nav>
          <NavLink
            to="/"
            className="nav-link"
          >
            Home
          </NavLink>
          <NavLink
            to="/library"
            className="nav-link"
          >
            Library
          </NavLink>
          <NavLink
            to="/donate"
            className="nav-link"
          >
            Donate
          </NavLink>
        </nav>
    </div>
  );
}
```
And while we're at it, we should add outlet context so that we can choose which portions of the app we want to conditionally render. This time, we'll need to use the children variable of our router.

```
const routes = [
    {
        path: "/",
        element: <App />,
        errorElement: <ErrorPage />,
        children: [
            {
                path: "/",
                element: <Home />,
            }, 
            {
                path: "/library",
                element: <Library />
            },
            {
                path: "/donate",
                element: <DonationForm />
            }
        ]
    }
];
```

This way, the default path leads to app, and app has children that it can choose to render through outlet context.

```
    return(
        <>
            <header>
                <Header />
                <NavBar />
            </header>
            <Outlet context={data}/>
        </>
    );
```

Here, the Header and NavBar components will always render, the Outlet is whatever child we are currently routed to. Data is whatever information we want to pass to the child component.
If we'd like to use the data we pass through context, we need to import and use the function useOutletContext().
```
import { useOutletContext } from "react-router-dom";

function DonationForm(){
    const data = useOutletContext()
```

We can also pass objects this way using destructuring.
```
<Outlet context={{books: books, setBooks: setBooks}}/>
```

```
const {books, setBooks} = useOutletContext()
```

Routing is neat!