# 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](https://reactrouter.com/en/main) 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:

```jsx
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**

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

// ...

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

To define routes:

**App.jsx**

```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**

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

// ...

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

**`NavLink`**

`NavLink`s 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**

```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

```jsx
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`:

```jsx
<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:

```jsx
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.

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

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

```jsx
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:

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