If you’ve ever built a web app, there’s a good chance you’ve built a tabbed document interface at one point or another. Tabs allow you to break up complex interfaces into manageable subsections that a user can quickly switch between. Tabs are a common UI component and are important to understand how to implement.
In this article, you will learn how to create a reusable tab container component that you can use by itself or with your existing components.
Before you begin this guide, you’ll need the following:
This tutorial was tested on Node.js version 10.20.1 and npm version 6.14.4.
In this step, you’ll create a new project using Create React App. You will then delete the sample project and related files that are installed when you bootstrap the project.
To start, make a new project. In your terminal, run the following script to install a fresh project using create-react-app
:
- npx create-react-app react-tabs-component
After the project is finished, change into the directory:
- cd react-tabs-component
In a new terminal tab or window, start the project using the Create React App start script. The browser will auto-refresh on changes, so leave this script running while you work:
- npm start
This will start a locally running server. If the project did not open in a browser window, you can open it by visiting http://localhost:3000/
. If you are running this from a remote server, the address will be http://your_domain:3000
.
Your browser will load with a template React application included as part of Create React App:
You will be building a completely new set of custom components, so you’ll need to start by clearing out some boilerplate code so that you can have an empty project.
To start, open src/App.js
in a text editor. This is the root component that is injected into the page. All components will start from here. You can find more information about App.js
at How To Set Up a React Project with Create React App.
You will see a file like this:
import React from 'react';
import logo from './logo.svg';
import './App.css';
function App() {
return (
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<p>
Edit <code>src/App.js</code> and save to reload.
</p>
<a
className="App-link"
href="https://reactjs.org"
target="_blank"
rel="noopener noreferrer"
>
Learn React
</a>
</header>
</div>
);
}
export default App;
Delete the line import logo from './logo.svg';
. Then replace everything in the return
statement to return a set of div
tags and an h1
. This will give you a valid page that returns an h1
that displays Tabs Demo. The final code will look like this:
import React from 'react';
import './App.css';
function App() {
return (
<div>
<h1>Tabs Demo</h1>
</div>
);
}
export default App;
Save and exit the text editor.
Finally, delete the logo. You won’t be using it in your application, and you should remove unused files as you work. It will save you from confusion in the long run.
In the terminal window type the following command to delete the logo:
- rm src/logo.svg
Now that the project is set up, you can create your first component.
Tabs
ComponentIn this step, you will create a new folder and the Tabs
component that will render each Tab
.
First, create a folder in the src
directory called components
:
- mkdir src/components
Inside the components
folder, create a new file called Tabs.js
:
- nano src/components/Tabs.js
Add the following code to the new Tabs.js
file:
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import Tab from './Tab';
These are the imports you need to create this component. This component will keep track of which tab is active, display a list of tabs, and the content for the active tab.
Next, add the following code that will be used to keep track of state and display the active tab below the imports
in Tabs.js
:
...
class Tabs extends Component {
static propTypes = {
children: PropTypes.instanceOf(Array).isRequired,
}
constructor(props) {
super(props);
this.state = {
activeTab: this.props.children[0].props.label,
};
}
onClickTabItem = (tab) => {
this.setState({ activeTab: tab });
}
...
The initial state is added for the active tab and will start at 0
in the array of tabs you will be creating.
onClickTabItem
will update the app state to the current tab that is clicked by the user.
Now you can add your render function to the same file:
...
render() {
const {
onClickTabItem,
props: {
children,
},
state: {
activeTab,
}
} = this;
return (
<div className="tabs">
<ol className="tab-list">
{children.map((child) => {
const { label } = child.props;
return (
<Tab
activeTab={activeTab}
key={label}
label={label}
onClick={onClickTabItem}
/>
);
})}
</ol>
<div className="tab-content">
{children.map((child) => {
if (child.props.label !== activeTab) return undefined;
return child.props.children;
})}
</div>
</div>
);
}
}
export default Tabs;
This component keeps track of which tab is active, displays a list of tabs, and the content for the active tab.
The Tabs
component uses the next component you will create called Tab
.
Tab
ComponentIn this step, you will create the Tab
component that you will use to create individual tabs.
Create a new file called Tab.js
inside the components
folder:
- nano src/components/Tab.js
Add the following code to the Tab.js
file:
import React, { Component } from 'react';
import PropTypes from 'prop-types';
Once again, you import React from react
and import PropTypes
. PropTypes
is a special propTypes
property used to run type-checking on props in a component.
Next, add the following code below the import
statements:
...
class Tab extends Component {
static propTypes = {
activeTab: PropTypes.string.isRequired,
label: PropTypes.string.isRequired,
onClick: PropTypes.func.isRequired,
};
onClick = () => {
const { label, onClick } = this.props;
onClick(label);
}
render() {
const {
onClick,
props: {
activeTab,
label,
},
} = this;
let className = 'tab-list-item';
if (activeTab === label) {
className += ' tab-list-active';
}
return (
<li
className={className}
onClick={onClick}
>
{label}
</li>
);
}
}
export default Tab;
The PropTypes
in this component are used to ensure that activeTab
and label
are a string and required. onClick
is set to be a function that is also required.
The Tab
component displays the name of the tab and adds an additional class if the tab is active. When clicked, the component will fire a handler, onClick
, that will let the Tabs
component know which tab should be active.
In addition to creating components, you will add CSS to give the components the appearance of tabs.
Inside the App.css
file, remove all the default CSS and add this code:
[label react-tabs-component/src/App.css] .tab-list {
border-bottom: 1px solid #ccc;
padding-left: 0;
}
.tab-list-item {
display: inline-block;
list-style: none;
margin-bottom: -1px;
padding: 0.5rem 0.75rem;
}
.tab-list-active {
background-color: white;
border: solid #ccc;
border-width: 1px 1px 0 1px;
}
This will make the tabs in-line and give the active
tab a border to make it stand out when clicked.
App.js
Now that the components and associated styles are in place, update the App
component to use them.
First, update the imports to include the Tabs
component:
import React from 'react';
import Tabs from "./components/Tabs";
import "./App.css";
Next, update the code in the return statement to include the imported Tabs
component:
...
function App() {
return (
<div>
<h1>Tabs Demo</h1>
<Tabs>
<div label="Gator">
See ya later, <em>Alligator</em>!
</div>
<div label="Croc">
After 'while, <em>Crocodile</em>!
</div>
<div label="Sarcosuchus">
Nothing to see here, this tab is <em>extinct</em>!
</div>
</Tabs>
</div>
);
}
export default App;
The div
s with associated labels give the tabs their content.
With Tabs
added to the App
component, you will now have a working tabbed interface that allows you to toggle between sections:
You can view this Github Repository to see the completed code.
In this tutorial, you built a tab component using React to manage and update your application’s state.
From here, you can learn other ways to style React components to create an even more attractive UI.
You can also follow the full How To Code in React.js series on DigitalOcean to learn even more about developing with React.
Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.
This textbox defaults to using Markdown to format your answer.
You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!
Is it possible to set a specific tab as active rather than default to the first one listed?
If you have any kind of esLint running it’s going to complain that this is not keyboard accessible. It will be best make them tab-able and selectable for users without a mouse if you’re going to put them out on the open web
hi joshtronic, thank you for this tutorial!
Question, what if the data that I will be displaying in tabs are from my API. How can I filter and dynamically pull the data?
I’m new to React.
Thank you joshtronic, this is a great articles and sample of code!
One question about tab.js ‘Anonymous Object’ (sorry I don’t know how to name it)
from tabs.js
Assigning this to an javascript object without name? It is new to me and want to know more about it. Thank you very much!