Blog>
Snippets

Using the Compound Component Pattern with Next.js 14

Create a set of compound components that work together to handle a complex UI scenario, such as an accordion list.
import { useState, createContext, useContext } from 'react';

// Create a context for the accordion
const AccordionContext = createContext();

/* Accordion Compound Component */
export const Accordion = ({ children }) => {
  const [activeIndex, setActiveIndex] = useState(null);

  const contextValue = {
    activeIndex,
    setActiveIndex
  };

  return (
    <AccordionContext.Provider value={contextValue}>
      <div>{children}</div>
    </AccordionContext.Provider>
  );
};

// Accordion Item Component
export const AccordionItem = ({ index, children }) => {
  const { activeIndex, setActiveIndex } = useContext(AccordionContext);

  const isOpen = index === activeIndex;

  const handleToggle = () => {
    setActiveIndex(isOpen ? null : index);
  };

  return (
    <div>
      <button onClick={handleToggle}>{children}</button>
      {isOpen && <div>{children}</div>}
    </div>
  );
};
This code block defines two components using the compound component pattern to create an accordion. The Accordion component sets up the AccordionContext with state to keep track of the active accordion item, which is shared among AccordionItem components. Each AccordionItem component uses the context to toggle its open state and render its children conditionally.