Introduction

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.

Prerequisites

Before you begin this guide, you’ll need the following:

You will need a development environment running Node.js. To install this on macOS or Ubuntu 18.04, follow the steps in How to Install Node.js and Create a Local Development Environment on macOS or the Installing Using a PPA section of How To Install Node.js on Ubuntu 18.04.
In this tutorial, you will create apps with Create React App. You can find instructions for installing an application with Create React App at How To Set Up a React Project with Create React App
You will also need a basic knowledge of JavaScript, which you can find in How To Code in JavaScript, along with a basic knowledge of HTML and CSS. A good resource for HTML and CSS is the Mozilla Developer Network.

This tutorial was tested on Node.js version 10.20.1 and npm version 6.14.4.

Step 1 — Creating an Empty Project

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:
react-tabs-component/src/App.js

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:
react-tabs-component/src/App.js


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.

Step 2 — Creating the Tabs Component

In 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:
react-tabs-component/src/components/Tabs.js

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:
react-tabs-component/src/components/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 `` 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:
react-tabs-component/src/components/Tabs.js

...

  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 Tabscomponent uses the next component you will create called Tab.

Step 3 — Creating the Tab Component

In 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:
react-tabs-component/src/components/Tab.js


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:
react-tabs-component/src/components/Tab.js

...
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.

Step 4 — Adding CSS to Style the App

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.

Step 5 — Updating 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:
react-tabs-component/src/App.js

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 divs 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.

Conclusion

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.