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.
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
.
1import React from "react";
2import ReactDOM from "react-dom";
3import App from "./App";
4import { BrowserRouter, Route, Redirect, Switch } from "react-router-dom";
5
6const routes = (
7 <BrowserRouter>
8 <Switch>
9 <Route path="/home" component={App} />
10 <Redirect from="/" to="/home" />
11 </Switch>
12 </BrowserRouter>
13);
14
15ReactDOM.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 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.
1const Profile = () => <div>You're on the Profile Tab</div>;
2const Comments = () => <div>You're on the Comments Tab</div>;
3const 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.
1import { Link } from "react-router-dom";
2
3class App extends Component {
4 render() {
5 return (
6 <div>
7 <h1>Hey welcome home!</h1>
8 <div className="links">
9 <Link to={`/`} className="link">Profile</Link>
10 <Link to={`/home/comments`} className="link">Comments</Link>
11 <Link to={`/home/contact`} className="link">Contact</Link>
12 </div>
13 </div>
14 );
15 }
16}
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.
1import { Switch, Route, Link } from "react-router-dom";
2
3<div className="tabs">
4 <Switch>
5 <Route path={`/home`} exact component={Profile} />
6 <Route path={`/home/comments`} component={Comments} />
7 <Route path={`/home/contact`} component={Contact} />
8 </Switch>
9</div>
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} />
.
1render() {
2 const { path } = this.props.match;
3
4 return (
5 <div>
6 <h1>Hey welcome home!</h1>
7 <div className="links">
8 <Link to={`${path}`} className="link">Profile</Link>
9 <Link to={`${path}/comments`} className="link">Comments</Link>
10 <Link to={`${path}/contact`} className="link">Contact</Link>
11 </div>
12 <div className="tabs">
13 <Switch>
14 <Route path={`${path}`} exact component={Profile} />
15 <Route path={`${path}/comments`} component={Comments} />
16 <Route path={`${path}/contact`} component={Contact} />
17 </Switch>
18 </div>
19 </div>
20 );
21}
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.
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
.
1const routes = (
2 <BrowserRouter>
3 <Switch>
4 <Route path="/crazyCoolNewRoute" component={App} />
5 <Redirect from="/" to="/crazyCoolNewRoute" />
6 </Switch>
7 </BrowserRouter>
8);
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.