DEV Community

Arafat Ahmed
Arafat Ahmed

Posted on

Compound Component Design Pattern in React

Compound component

Compound component is a design pattern in React
that allows you to create reusable components that
encapsulate logic and state.

This can make your code more modular and easier to maintain.

The compound pattern can be a powerful tool for creating reusable and maintainable React components.

Here are some of the benefits of using compound components:

  • Modular code: Compound components can help you break down your code into smaller, more manageable pieces. This can make your code easier to understand, test, and maintain.
  • Reusable code: Compound components can be reused in multiple places throughout your application. This can save you time and effort when developing your application.
  • Encapsulated state: Compound components can encapsulate state within themselves. This can make your code more predictable and easier to reason about. If you are developing a large React application, I recommend using compound components to help you organize your code and make it more maintainable.

EXAMPLE :

We are going to build a Tab component here to demonstrate the
Compound component design pattern.

import React, { useState } from "react";

import Tab from "./Tab";

function App() {
  const [currentTab, setCurrentTab] = useState(0);
  const handleCurrentTab = (tabIndex) => {
    setCurrentTab(tabIndex);
  };

  return (
    <div className="App">
      <Tab value={currentTab} onChange={handleCurrentTab}>
        <Tab.Heads>
          <Tab.Item label="Tab 1" index={0} />
          <Tab.Item label="Tab 2" index={1} />
          <Tab.Item label="Tab 3" index={2} />
        </Tab.Heads>

        <Tab.ContentWrapper>
          <Tab.Content index={0}> Content 1 </Tab.Content>
          <Tab.Content index={1}> Content 2 </Tab.Content>
          <Tab.Content index={2}> Content 3 </Tab.Content>
        </Tab.ContentWrapper>
      </Tab>
    </div>
  );
}

export default App;
Enter fullscreen mode Exit fullscreen mode

This App.js file contains the presentation structure of the Tab Component.

The Tab component has four children:

  • Tab.Heads component : The Tab.Heads component is responsible for rendering the tab header.
  • Tab.Item component : The Tab.Item component is used to render the tab label.
  • Tab.ContentWrapper component : The Tab.ContentWrapper component is responsible for rendering the content areas.
  • Tab.Content component: The Tab.Content component is responsible for rendering the content for a specific tab.
import React, { useContext, createContext } from "react";

const TabContext = createContext();

export default function Tab({ children, value, onChange }) {
  return (
    <TabContext.Provider value={{ value, onChange }}>
      {children}
    </TabContext.Provider>
  );
}

const Heads = ({ children }) => <div> {children} </div>;

const Item = ({ label, index, children }) => {
  const { onChange } = useContext(TabContext);
  const handleClick = () => {
    return onChange(index);
  };

  return <div onClick={handleClick}> {label} </div>;
};

const ContentWrapper = ({ children }) => <div> {children} </div>;

const Content = ({ children, index }) => {
  const { value } = useContext(TabContext);

  return index === value ? <div> {children} </div> : null;
};

Tab.Heads = Heads;
Tab.Item = Item;
Tab.ContentWrapper = ContentWrapper;
Tab.Content = Content;
Enter fullscreen mode Exit fullscreen mode

This is our Tab.js file where we implement all the logical parts for this component.
The Tab component uses the useContext hook to access the context object.
The Heads component uses the children's prop to render the tab labels.
The Item component uses the label, index, and children props to render a tab label and a content area.
The ContentWrapper component uses the children's prop to render the content areas.
The Content component uses the children and index props to render the content for a specific tab.
Here we decouple our Content and Item component in such a way that we can pass any component as content or tab item.

Top comments (0)