React Router

React is a library for creating User Interfaces, not a full, batteries-included framework. You'll have to supply your own batteries such as a router for URL and link handling.

React Router

React Router is a package that allows us to change the URL, making it look like the user is visiting different pages, when they are actually still on the same page. This is a common pattern in Single-Page Applications (SPAs).

It takes care of two tasks that are traditionally accomplished by going to different pages:

  1. It keeps track of what is supposed to happen and which components should be rendered when you visit specific URLs.

  2. It updates the browser's history with those URLs.

The second piece happens automatically; the first part is what you have to set up. Setting up routes for React Router is very similar to setting up routes in Express and Flask. You define the same basic things: the path, and what should happen when that path is visited. The only difference is that it will do the routing on the client, without actually hitting your server.

Setting Up React Router

Install the react-router-dom package:

npm i react-router-dom

We usually want our whole app to be managed by React Router so we wrap our App component in a BrowserRouter component.

main.jsx

import { BrowserRouter } from 'react-router-dom';

// ...

root.render(
  <React.StrictMode>
    <BrowserRouter>
      <App />
    </BrowserRouter>
  </React.StrictMode>
)

To define routes:

App.jsx

const Index = () => {
  return <h2>Index Page</h2>;
};

const Page1 = () => {
  return <h2>Page 1</h2>;
};

const Page2 = () => {
  return <h2>Page 2</h2>;
};

const App = () => {
  return (
    <>
      <h1>App</h1>
      <Routes>
        <Route path="/" element={<Index />} />
        <Route path="/page-1" element={<Page1 />} />
        <Route path="/page-2" element={<Page2 />} />
      </Routes>
    </>
  );
};

export default App;

Linking to Routes

Link

App.jsx

import { Routes, Route, Link } from 'react-router-dom';

// ...

<Link to="/page-1">Page 1</Link>
<Link to="/page-2">Page 2</Link>

NavLink

NavLinks are similar to links but with the added feature of setting an 'active' CSS class on itself if its route is the current one.

App.jsx

import { Routes, Route, Link, NavLink } from 'react-router-dom';

// ...

const Nav = () => {
  return (
    <nav>
      <NavLink to="/">Index</NavLink>
      <NavLink to="/page-1">Page 1</NavLink>
      <NavLink to="/page-2">Page 2</NavLink>
    </nav>
  );
};

404 Routes

const NotFound = () => {
  return <h2>404 Not Found</h2>
};

//...

<Routes>
  <Route path="/" element={<Index />} />
  <Route path="/page-1" element={<Page1 />} />
  <Route path="/page-2" element={<Page2 />} />
  <Route path="*" element={<NotFound />} />
</Routes>

Nested Routes

With React Router, we can route users not just page to page but to specific fragments of UI in the same page using nested routes.

Define nested routes for /settings:

<Route path="/settings" element={<SettingsIndex />}>
  <Route path="profile" element={<ProfileSettings />} />
  <Route path="account" element={<AccountSettings />} />
</Route>

Add an Outlet component to tell React Router where in the parent component (SettingsIndex) to render the child:

import { Outlet } from 'react-router-dom'
const SettingsIndex = () => {
  return (
    <div>
      <h1>Settings</h1>
      <Outlet />
    </div>
  );
};

Dynamic Routes

We can also define dynamic routes with React Router much like Express' and Flask's router.

<Route path="/users/:username" element={<UserProfile />} />

To access the dynamic URL param value in the component, we use the useParams hook:

import { useParams } from 'react-router-dom';

const UserProfile = () => {
  const { username } = useParams();
  console.log(username);
};

We can then link to a specific user profile page via the username:

<Link to={`/users/${user.username}`}>{user.username}</Link>

Last updated