DEV Community

Chevy Vall
Chevy Vall

Posted on

Routing, Client Side

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
Enter fullscreen mode Exit fullscreen mode

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"
Enter fullscreen mode Exit fullscreen mode

Next we create our router object using the imported function.

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

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} />);
)
Enter fullscreen mode Exit fullscreen mode

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} />);
)
Enter fullscreen mode Exit fullscreen mode

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 />
  }
]);
Enter fullscreen mode Exit fullscreen mode

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>
  );
}
Enter fullscreen mode Exit fullscreen mode

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 />
            }
        ]
    }
];
Enter fullscreen mode Exit fullscreen mode

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}/>
        </>
    );
Enter fullscreen mode Exit fullscreen mode

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()
Enter fullscreen mode Exit fullscreen mode

We can also pass objects this way using destructuring.

<Outlet context={{books: books, setBooks: setBooks}}/>
Enter fullscreen mode Exit fullscreen mode
const {books, setBooks} = useOutletContext()
Enter fullscreen mode Exit fullscreen mode

Routing is neat!

Top comments (0)