Check your version
This post assumes you're using React Router v5. If not, find your version below.A common UI pattern is to have a sidebar or breadcrumb navbar in your app. Because React Router v5 allows you to render and match more than one Route
per page, implementing this pattern is pretty straight forward. The goal of this post is to show how you can, by rendering multiple Route
s, render separate components at separate parts of your page (like a sidebar).
The first thing we'll do, and really the secret implementing a sidebar or breadcrumbs, is to create a routes
array. Each item in the array is going to contain all the information about the specific route, including which component should be rendered.
const routes = [{path: "/",exact: true,sidebar: () => <div>home!</div>,main: () => <h2>Home</h2>,},{path: "/bubblegum",sidebar: () => <div>bubblegum!</div>,main: () => <h2>Bubblegum</h2>,},{path: "/shoelaces",sidebar: () => <div>shoelaces!</div>,main: () => <h2>Shoelaces</h2>,},];
Now, because we've abstracted our routes to this array, whenever we want to render any Route
s, we can map over it and specify which component should be rendered (main
or sidebar
).
To show how this is done, let's first build out the basic skeleton for our app.
import * as React from "react";import { BrowserRouter as Router, Route, Link } from "react-router-dom";const routes = [{path: "/",exact: true,sidebar: () => <div>home!</div>,main: () => <h2>Home</h2>,},{path: "/bubblegum",sidebar: () => <div>bubblegum!</div>,main: () => <h2>Bubblegum</h2>,},{path: "/shoelaces",sidebar: () => <div>shoelaces!</div>,main: () => <h2>Shoelaces</h2>,},];export default function App() {return (<Router><div style={{ display: "flex" }}><divstyle={{padding: "10px",width: "40%",}}><ul style={{ listStyleType: "none", padding: 0 }}><li><Link to="/">Home</Link></li><li><Link to="/bubblegum">Bubblegum</Link></li><li><Link to="/shoelaces">Shoelaces</Link></li></ul></div></div></Router>);}
Remember, the goal here is to render multiple components in different places of the app, based on the app's path. We already have our routes
array, so wherever we want to render some Route
s we can map over it. First, let's add some Route
s to the sidebar (inside of our nav).
export default function App() {return (<Router><div style={{ display: "flex" }}><divstyle={{padding: "10px",width: "40%",}}><ul style={{ listStyleType: "none", padding: 0 }}><li><Link to="/">Home</Link></li><li><Link to="/bubblegum">Bubblegum</Link></li><li><Link to="/shoelaces">Shoelaces</Link></li></ul>{routes.map((route) => (<Route key={route.path} path={route.path} exact={route.exact}><route.sidebar /></Route>))}</div></div></Router>);}
The biggest thing to notice is that we've passed route.sidebar
to Route
s component
prop. This is the crux of the example and shows the importance of the routes
array we created earlier. Now whenever the app's location matches the path
, the sidebar component will be rendered. However, we don't just want to stop there. We also want to render a component in the main body of our app as well. To do that, we'll map over routes
again but instead of component
being route.sidebar
, we'll pass it route.main
.
export default function App() {return (<Router><div style={{ display: "flex" }}><divstyle={{padding: "10px",width: "40%",}}><ul style={{ listStyleType: "none", padding: 0 }}><li><Link to="/">Home</Link></li><li><Link to="/bubblegum">Bubblegum</Link></li><li><Link to="/shoelaces">Shoelaces</Link></li></ul>{routes.map((route) => (<Route key={route.path} path={route.path} exact={route.exact}><route.sidebar /></Route>))}</div><div style={{ flex: 1, padding: "10px" }}>{routes.map((route) => (<Route key={route.path} path={route.path} exact={route.exact}><route.main /></Route>))}</div></div></Router>);}
Because React Router v5 allows us to render and match more than one Route
on a page, and because we abstracted our routes to their own array, we can render different components at different sections of our page whenever the app's location matches the Route
s path
.