DEV Community

Cover image for Compound Components and Layout Components in React
PrinceRajRoy
PrinceRajRoy

Posted on

Compound Components and Layout Components in React

Hello!

Writing resilient components with flexible composition is a bit tricky in React. In this post we will see the difference, how and when to use layout and compound components. Let's get started.

Layout Components

These component are used for creating reusable layouts in a react app. They accept UI trees as props and then position them as required visually. The props are basically used to fill up holes in the layout component UI, it's upto this component to position them in correct places.

One important thing to note is that Layout Components don't usually need their own state but there could be use cases depending on the situation (mostly state related to UI rather than external data).

When we start building a website from scratch it's always a good idea to visualize the UI in respect of the different parts that can be abstracted into it's own component. As an example below is the homepage of this website.
Dev.to Homepage

As we can see, the website can be divided into 3 main parts, the Left Sidebar, Main View and the Right Sidebar. So normally using composition we will write it as,

function App() {
  return (
    <div>
      <Home
        leftSidebar={
          <LeftSidebar>
            <Community />
            <Other />
          </LeftSidebar>
        }
        mainView={
          <MainView>
            <Header />
            <Feed />
          </MainView>
        }
        rightSidebar={
          <RightSidebar>
            <Listings />
            <News />
          </RightSidebar>
        }
      />
    </div>
  )
}

function LeftSidebar({ children }) {
  return <div>{children}</div>
}

function MainView({ children }) {
  return <div>{children}</div>
}

function RightSidebar({ children }) {
  return <div>{children}</div>
}

function Home({ leftSidebar, mainView, rightSidebar }) {
  return (
    <div>
      {leftSidebar}
      {mainView}
      {rightSidebar}
    </div>
  )
}
Enter fullscreen mode Exit fullscreen mode

We can apply different styling to each of these abstracted components and position them as and when required in Home Component, each prop here fills a hole in the UI.

Compound Components

These components also use composition model, the simplest overview of these types components can be found in the <select>/<option> tag in html. These tags have a implicit state that enables it to show the currently selected option while still giving the developer full access to the rendering logic for each of the pieces.
For example if we want to disable one of the options in the UI we can easily do it

  <select value={value}>
    {options.map(option => (
       <option value={option} disabled={option === disableValue} />
    )}
  </select>
Enter fullscreen mode Exit fullscreen mode

We can create components based on this concept, such existing UI Libraries or from scratch, we will be using Menu Component and it's option equivalent MenuItem provided by MUI.

Here, in ListMenu Component, we are managing the state as well as using MUI components in a coherent way.

   <Menu
      anchorEl={anchorEl}
      open={open}
      onClose={handleClose}
    >
     {options.map((option, index) => (
       <MenuItem
         key={option}
         disabled={index === 0}
         selected={index === selectedIndex}
         onClick={(event) => handleMenuItemClick(event, index)}
       >
         {option}
       </MenuItem>
     ))}
   </Menu>
Enter fullscreen mode Exit fullscreen mode

We can change the styles based on the requirements, disable some options (first option is disabled) and much more, add images along with text? sure, we can customize as much as we want.

Other developers can use this abstraction without worrying about handling state, they can customize styles by passing className to the component as a prop. And that's Compound Components!

I loved writing this post. If you have any questions or suggestions, feel free to reach out to me!

Connect with me on Twitter, Github

Top comments (0)