This post was originally published at https://www.devaradise.com/react-tabs-tutorial
Tab is a common component in web applications that organize content in different views. Tabs allow us to break up complex interfaces into more manageable subsections that a user can quickly switch between.
In a React project, we can implement tabs component in many ways. In this post, I am going to show you how to implement react tabs using 3 different ways, with the demo examples.
We will create a manual tabs component using react state hooks, a routed react tabs using react-router-dom, and easy React tabs component using react-tabs library.
With these 3 different ways, I hope you find the right way to implement tabs component that suits your project.
Before we begin, as always, I assume that you’re already know how to initialize a react project using create-react-app because I won’t explain it anymore.
I also use functional component and Hooks to manage state in the component as it is more simple and cleaner than using class-based component.
How to Implement React Tabs with State Hooks
Implementing react tabs using state hooks is suitable if you don't want to use any tabs library. You just want to create a simple tabs component that managed by useState()
hook.
Here is how to implement it.
import React, { useState } from 'react'
export default function WithStateHook() {
const [currentTab, setCurrentTab] = useState('tab1');
const tabList = [
{
name: 'tab1',
label: 'Tab 1',
content: (
<div className="tab-content">
<h2>Tab content 1</h2>
<p>Here is your tab content. You can separate this as a component.</p>
<p>Lorem ipsum dolor sit amet ...</p>
</div>
)
},
{
name: 'tab2',
label: 'Tab 2',
content: (
<div className="tab-content">
<h2>Tab content 2</h2>
<p>Here is your tab content. You can separate this as a component.</p>
<p>Lorem ipsum dolor sit amet ...</p>
</div>
)
},
{
name: 'tab3',
label: 'Tab 3',
content: (
<div className="tab-content">
<h2>Tab content 3</h2>
<p>Here is your tab content. You can separate this as a component.</p>
<p>Lorem ipsum dolor sit amet ...</p>
</div>
)
}
];
return (
<div className="simple-tabs">
<h1>With State Hook</h1>
<div className="tabs">
{
tabList.map((tab, i) => (
<button
key={i}
onClick={() => setCurrentTab(tab.name)}
className={(tab.name === currentTab) ? 'active' : ''}>
{tab.label}
</button>
))
}
</div>
{
tabList.map((tab, i) => {
if(tab.name === currentTab) {
return <div key={i}>{tab.content}</div>;
} else {
return null;
}
})
}
</div>
)
}
With using state hook, the simplest way I found to implement tabs component is by declaring a currentTab
state and a tabList
variable that stores all tab data in an array.
The logic is simple. You just loop the tabList
and show the only tab that has matched name
value with currentTab
value.
The currentTab
value will changes as the user clicks a tab. It handled in onClick
event attribute in tab markup.
I use button
tag for the tab because when I use a
tag without href
or with invalid href
value (#), it returns an error from eslint-plugin-jsx.
I tried to resolve error with eslint-disable-next-line
and it works. But, when i built it, the tabs component doesn't render.
I think, React is encouraging us to follow that rule. So, i just follow them.
Back to the codes, you can change the tabList
to become a react prop or state if you want to make it dynamic.
For instance, if you want to make this tab component reusable and shared in your project, you can make the tabList
as a prop. So, you can pass the tabList
value from any component in your project.
If you want to see the demo you can click this link. As for the codes, you can clone my react-lab repository on github. It contains all demo examples for all react tutorials I wrote in this blog.
How to Implement Routed React Tabs with react-router-dom
Routed tabs component means that each tab has its own route / URL. When a tab clicked, the route will changes. So, this is the best choice if you care about SEO, or simply just want to directly access a tab via URL.
You can implement a routed tabs component using react-router-dom, a popular router library for React.
Before creating a routed tabs component, make sure you install react-router-dom first in your project.
npm install react-router-dom
After that, you should import react-router-dom in your component like this.
import { Route, Switch, NavLink } from 'react-router-dom'
You should also make sure that your component or its parent component are wrapped inside BrowserRouter
because Route
only works inside BrowserRouter
.
<BrowserRouter>
<Route exact component={Home} path="/"/>
<Route component={ReactTabs} path="/react-tabs-component"/>
</BrowserRouter>
Usually, BrowserRouter
added in root component like App.js.
Then, you can implement the codes below.
Simple Implementation
For this simple implementation, you can just use repeated NavLink
for tab menu, Route
for tab content, and Switch
to make it work as tabs.
import React from 'react'
import { Route, Switch, NavLink } from 'react-router-dom'
export default function RoutedTabs(props) {
const parentPath = props.match.path;
return (
<div className="routed-tabs">
<h1>Routed Tabs</h1>
<div className="tabs">
<NavLink
to={parentPath+'/tab-1'}
activeClassName="active"
isActive={(match, location) =>
[parentPath, parentPath+'/tab-1'].includes(location.pathname)
}
>
Tab 1
</NavLink>
<NavLink
to={parentPath+'/tab-2'}
activeClassName="active"
isActive={(match, location) =>
[parentPath+'/tab-2'].includes(location.pathname)
}
>
Tab 2
</NavLink>
<NavLink
to={parentPath+'/tab-3'}
activeClassName="active"
isActive={(match, location) =>
[parentPath+'/tab-3'].includes(location.pathname)
}
>
Tab 3
</NavLink>
</div>
<Switch>
<Route component={
() => (<div className="tab-content">
<h2>Tab content 1</h2>
<p>Here is your tab content. You can separate this as a component.</p>
<p>Lorem ipsum dolor sit amet ...</p>
</div>)
} exact path={[parentPath, parentPath+"/tab-1"]}/>
<Route component={
() => (<div className="tab-content">
<h2>Tab content 2</h2>
<p>Here is your tab content. You can separate this as a component.</p>
<p>Lorem ipsum dolor sit amet ...</p>
</div>)
} path={[parentPath+"/tab-2"]}/>
<Route component={
() => (<div className="tab-content">
<h2>Tab content 3</h2>
<p>Here is your tab content. You can separate this as a component.</p>
<p>Lorem ipsum dolor sit amet ...</p>
</div>)
} path={[parentPath+"/tab-3"]}/>
</Switch>
</div>
)
}
As you can see, the codes above don't have much logic as it's for static tabs.
If you want to make a dynamic tabs component like when we implement tabs using state hook, you can see the codes below.
Dynamic Implementation
import React from 'react'
import { Route, Switch, NavLink } from 'react-router-dom'
export default function RoutedTabsDynamic(props) {
const parentPath = props.match.path;
const tabsData = [
{
label: "Tab 1",
path: parentPath+"/tab-1",
content: (<div className="tab-content">
<h2>Tab content 1</h2>
<p>Here is your tab content. You can separate this as a component.</p>
<p>Lorem ipsum dolor sit amet ...</p>
</div>),
defaultTab: true
},
{
label: "Tab 2",
path: parentPath+"/tab-2",
content: (<div className="tab-content">
<h2>Tab content 2</h2>
<p>Here is your tab content. You can separate this as a component.</p>
<p>Lorem ipsum dolor sit amet ...</p>
</div>),
},
{
label: "Tab 3",
path: parentPath+"/tab-3",
content: (<div className="tab-content">
<h2>Tab content 3</h2>
<p>Here is your tab content. You can separate this as a component.</p>
<p>Lorem ipsum dolor sit amet ...</p>
</div>),
}
]
return (
<div className="routed-tabs">
<h1>Routed Tabs</h1>
<div className="tabs">
{tabsData.map((data, i) => {
return (
<NavLink
key={i}
to={data.path}
activeClassName="active"
isActive={(match, location) =>
data.defaultTab
? [parentPath, data.path].includes(location.pathname)
: [data.path].includes(location.pathname)
}
>
{data.label}
</NavLink>
);
})}
</div>
<Switch>
{tabsData.map((data, i) => {
return (
<Route
key={i}
component={() => data.content}
exact
path={
data.defaultTab
? [parentPath, data.path]
: [data.path]
}
/>
);
})}
</Switch>
</div>
)
}
The logic is the same with the implementation using state hook. The differences are just the markup to be looped.
To see the working demo for routed react tabs, you can click the link below.
How to Implement React Tabs with react-tabs
library
The last way to implement react tabs is by using a library. There are a lot of tabs libraries for React out there. But here, we're going to use react-tabs
.
First, you should install it on your project.
npm install react-tabs
Then, import react-tabs
to your component like below. You should also import the CSS as react-tabs
has pre-defined style.
import { Tab, Tabs, TabList, TabPanel } from 'react-tabs';
import 'react-tabs/style/react-tabs.css';
For full implementation of react-tabs, you can see the following codes.
import React from 'react'
import { Tab, Tabs, TabList, TabPanel } from 'react-tabs'
import 'react-tabs/style/react-tabs.css'
export default function WithReactTabs() {
return (
<div className="with-react-tabs">
<h1>With react-tabs</h1>
<Tabs>
<TabList>
<Tab>Tab 1</Tab>
<Tab>Tab 2</Tab>
<Tab>Tab 3</Tab>
</TabList>
<TabPanel>
<div className="tab-content">
<h2>Tab content 1</h2>
<p>Here is your tab content. You can separate this as a component.</p>
<p>Lorem ipsum dolor sit amet ...</p>
</div>
</TabPanel>
<TabPanel>
<div className="tab-content">
<h2>Tab content 2</h2>
<p>Here is your tab content. You can separate this as a component.</p>
<p>Lorem ipsum dolor sit amet ...</p>
</div>
</TabPanel>
<TabPanel>
<div className="tab-content">
<h2>Tab content 3</h2>
<p>Here is your tab content. You can separate this as a component.</p>
<p>Lorem ipsum dolor sit amet ...</p>
</div>
</TabPanel>
</Tabs>
</div>
)
}
That is just a static tabs implementation. If you want to make it dynamic, just follow the mechanism in the tabs component with state hook or routed tabs. The logic is the same.
That's all. I hope this helpful.
If you want to see similar react tutorials, you might interested with these:
- React Infinite Scroll Tutorial: With and Without A Library
- React Datepicker Tutorial with Top 2 Datepicker Libraries
Happy coding!
Top comments (1)
Nice!