Skip to content

Contact sales

By filling out this form and clicking submit, you acknowledge our privacy policy.

How to Create Nested Tab Routes with React Router

May 18, 2020 • 6 Minute Read

Introduction

Many developers make a habit of concealing redundant data behind tabs in web apps. Nevertheless, it's important to make sure that defining such tabs doesn't render the data inaccessible, especially when a user bookmarks or even shares the link. Because sharing on the web usually happens through URLs, you as a developer must implement a technique to retrieve the tab when a user clicks it. This is regardless of whether it is an absolute path or a mere query parameter.

Luckily, React Router comes to the rescue, not only with support for tabs but also with standard React patterns. This guide will cover creating nested tab routes with dynamic paths using React Router.

Set up Router

First things first: start by setting up the router to render your app. Import BrowserRouter and simply render a Switch to choose among routes. In reality, you only have a single route that you will assign the path /home to, while the component is actually your App.

      import React from "react";
import ReactDOM from "react-dom";
import App from "./App";
import { BrowserRouter, Route, Redirect, Switch } from "react-router-dom";

const routes = (
  <BrowserRouter>
    <Switch>
      <Route path="/home" component={App} />
      <Redirect from="/" to="/home" />
    </Switch>
  </BrowserRouter>
);

ReactDOM.render(routes, document.getElementById("root"));
    

Don't let Redirect scare you. It's only used so that upon navigating to /, it redirects to the home route.

Create Tabs

Create tabs within your App.js file. Remember that these will become your tab routes and thus the components that you'll render according to their URLs.

      const Profile = () => <div>You're on the Profile Tab</div>;
const Comments = () => <div>You're on the Comments Tab</div>;
const Contact = () => <div>You're on the Contact Tab</div>;
    

As you see, these components are the usual function React components.

The next step is setting up the links that will act as your tab controls. Set up your to links as absolute paths. In fact, this is the reason that you must include /home in both /comments and /contact. You already addressed / using redirect above.

      import { Link } from "react-router-dom";

class App extends Component {
  render() {
    return (
      <div>
        <h1>Hey welcome home!</h1>
        <div className="links">
          <Link to={`/`} className="link">Profile</Link>
          <Link to={`/home/comments`} className="link">Comments</Link>
          <Link to={`/home/contact`} className="link">Contact</Link>
        </div>
      </div>
    );
  }
}
    

Set up Nested Tabs

Now, it's time to set up your tabs. You do not need to configure static routes on top of tabs as React Router allows you to set up routes basically everywhere. Set up your path route to map to your to links.

Note that the exact prop on the first route indicates a rigorous match. In other words, you must be exactly at /home in order to be at the Profile tab. The exact prop is not used to render the other tab routes.

      import { Switch, Route, Link } from "react-router-dom";

<div className="tabs">
  <Switch>
    <Route path={`/home`} exact component={Profile} />
    <Route path={`/home/comments`} component={Comments} />
    <Route path={`/home/contact`} component={Contact} />
  </Switch>
</div>
    

Make Tab Routes Dynamic

The above approach is very static, that is, you need to set your routes as absolute paths. Thus, if you later decide to alter your base route from /home to another route, you must edit every Route that includes it.

To avoid this hassle, configure your route paths dynamically according to the Route that matches above. Use the match prop to substitute whatever you have defined within <Route path="/home" component={App} />.

      render() {
  const { path } = this.props.match;

  return (
    <div>
      <h1>Hey welcome home!</h1>
      <div className="links">
        <Link to={`${path}`} className="link">Profile</Link>
        <Link to={`${path}/comments`} className="link">Comments</Link>
        <Link to={`${path}/contact`} className="link">Contact</Link>
      </div>
      <div className="tabs">
        <Switch>
          <Route path={`${path}`} exact component={Profile} />
          <Route path={`${path}/comments`} component={Comments} />
          <Route path={`${path}/contact`} component={Contact} />
        </Switch>
      </div>
    </div>
  );
}
    

As you can see above, to is dynamically set in the Link. The Route tabs that you set up are also dynamically configured according to match.path. Thus, you can append the extra path that you wish to match for each individual tab.

The advantages of this technique aren't limited to the dynamic routing. You can also now reuse your tabs. For instance, if you need to render tab routes with different tops and matching endings, you can reuse the tabs and automatically alter the top level only.

Change Top Level

No matter what you define at the top level, you can reuse the tabs. The following example demonstrates how to change the path from /home to /crazyCoolNewRoute.

      const routes = (
  <BrowserRouter>
    <Switch>
      <Route path="/crazyCoolNewRoute" component={App} />
      <Redirect from="/" to="/crazyCoolNewRoute" />
    </Switch>
  </BrowserRouter>
);
    

Conclusion

This guide covered the basics of React Router. Now you know how to create tabs, links, and nested tabs. You also learned how to reuse tabs by changing the top level. This is just the beginning as React Router's potentials are limitless.