DEV Community

Cover image for Rendering a Sidebar or Breadcrumbs with React Router v4
Tyler McGinnis
Tyler McGinnis

Posted on β€’ Originally published at tylermcginnis.com

21 4

Rendering a Sidebar or Breadcrumbs with React Router v4

When building an app with React Router, often you'll want to implement a sidebar or breadcrumb navbar. In this post you'll learn how that's done with React Router by breaking down the Sidebar example from the React Router documentation.

A common UI pattern is to have a sidebar or breadcrumb navbar in your app. Because React Router 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 Routes, render separate components at separate parts of your page based on the path (like a sidebar).

The first thing we'll do, and really the secret to this post, is to create a routes array. Each item in the array is going to contain all the information about the specific route, and also 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 Routes we can map over it and specify which component should be rendered (main or sidebar). To show how that's done, let's first build out the basic skeleton for our app.

import 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>
  }
]

class App extends React.Component {
  render() {
    return (
      <Router>
        <div style={{ display: 'flex' }}>
          <div style={{
            padding: '10px',
            width: '40%',
            background: '#f0f0f0'
          }}>
            <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>
    )
  }
}

export default App

Now remember the goal here is to render multiple components in different places of the app, based on the path. We already have our routes array, so wherever we want to render some Routes we can just map over it. First, let's add some Routes to the sidebar (inside of our nav).

render() {
  return (
    <Router>
      <div style={{ display: 'flex' }}>
        <div style={{
          padding: '10px',
          width: '40%',
          background: '#f0f0f0'
        }}>
          <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}
              component={route.sidebar}
            />
          ))}
        </div>
      </div>
    </Router>
  )
}

The biggest thing to notice is that we've passed in route.sidebar to Routes component prop. This is the crux of the example and shows the importance of the routes array we created earlier. Now whenever the 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 when the location matches the path. To do that, we'll map over routes again but instead of passing component route.sidebar, we'll pass it route.main.

render() {
  return (
    <Router>
      <div style={{ display: 'flex' }}>
        <div style={{
          padding: '10px',
          width: '40%',
          background: '#f0f0f0'
        }}>
          <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}
              component={route.sidebar}
            />
          ))}
        </div>

        <div style={{ flex: 1, padding: '10px' }}>
          {routes.map((route) => (
            <Route
              key={route.path}
              path={route.path}
              exact={route.exact}
              component={route.main}
            />
          ))}
        </div>
      </div>
    </Router>
  )
}

πŸ•Ί. Now, because React Router allows us to render and match more than one Route on a page, and because we abstracted our routes to an array, we can render different components at different sections of our page whenever the location matches the Routes path.


This was originally published at TylerMcGinnis.com and is part of their React Router course.

Do your career a big favor. Join DEV. (The website you're on right now)

It takes one minute, it's free, and is worth it for your career.

Get started

Community matters

Top comments (1)

Collapse
 
ghost profile image
Ghost β€’

Thanks Tyler your tutorials are relatively good in quality as compared to other stuff. Maybe at some point you can write about this: fiture.me/share/1165.html, however, for router v4.

11 Tips That Make You a Better Typescript Programmer

typescript

1 Think in {Set}

Type is an everyday concept to programmers, but it’s surprisingly difficult to define it succinctly. I find it helpful to use Set as a conceptual model instead.

#2 Understand declared type and narrowed type

One extremely powerful typescript feature is automatic type narrowing based on control flow. This means a variable has two types associated with it at any specific point of code location: a declaration type and a narrowed type.

#3 Use discriminated union instead of optional fields

...

Read the whole post now!

πŸ‘‹ Kindness is contagious

Engage with a sea of insights in this enlightening article, highly esteemed within the encouraging DEV Community. Programmers of every skill level are invited to participate and enrich our shared knowledge.

A simple "thank you" can uplift someone's spirits. Express your appreciation in the comments section!

On DEV, sharing knowledge smooths our journey and strengthens our community bonds. Found this useful? A brief thank you to the author can mean a lot.

Okay