728x90
728x90

Compound Component 패턴

들어가며

  • 리액트(React.js)에서 자주 사용되는 디자인 패턴(Design Pattern) 중 하나인 Compound Component 패턴에 대해 정리해본다.

 

Compound Component 패턴

개념

  • 서로 관련된 여러 개의 컴포넌트를 하나의 부모 컴포넌트 안에 캡슐화하는 방식
  • 컴파운드 컴포넌트의 주요 아이디어는 사용자 인터페이스(UI)를 구성하는 여러 작은 컴포넌트를 하나의 상위 컴포넌트 안에서 조합하여 더 복잡한 UI를 만드는 것이다.

 

Coompound Component 패턴의 적용 예 : @<select> - <option>@
<select>
    <option>Option 1</option>
    <option>Option 2</option>
    <option>Option 3</option>
    <option>Option 4</option>
</select>

 

장점

  • 동일한 컴포넌트를 다양한 방식으로 재사용할 수 있다.
  • 컴포넌트의 내부 구조를 변경하지 않고도 다양한 UI 구성을 만들 수 있다.
  • 복잡한 UI를 작은 컴포넌트로 나누어 구성함으로써 코드가 더 이해하기 쉽게 된다.

 

예제 코드

import React, { useState, createContext, useContext } from 'react';

const AccordionContext = createContext();

const Accordion = ({ children }) => {
  const [openIndex, setOpenIndex] = useState(null);

  const toggleIndex = (index) => {
    setOpenIndex((prevIndex) => (prevIndex === index ? null : index));
  };

  return (
    <AccordionContext.Provider value={{ openIndex, toggleIndex }}>
      <div className="accordion">{children}</div>
    </AccordionContext.Provider>
  );
};

const AccordionItem = ({ children, index }) => {
  const { openIndex, toggleIndex } = useContext(AccordionContext);
  const isOpen = openIndex === index;

  return (
    <div className={`accordion-item ${isOpen ? 'open' : ''}`}>
      {React.Children.map(children, (child) =>
        React.cloneElement(child, { isOpen, index, toggleIndex })
      )}
    </div>
  );
};

const AccordionHeader = ({ children, index, toggleIndex }) => (
  <div className="accordion-header" onClick={() => toggleIndex(index)}>
    {children}
  </div>
);

const AccordionBody = ({ children, isOpen }) => (
  isOpen ? <div className="accordion-body">{children}</div> : null
);

const App = () => (
  <Accordion>
    <AccordionItem index={0}>
      <AccordionHeader>Header 1</AccordionHeader>
      <AccordionBody>Body 1 Content</AccordionBody>
    </AccordionItem>
    <AccordionItem index={1}>
      <AccordionHeader>Header 2</AccordionHeader>
      <AccordionBody>Body 2 Content</AccordionBody>
    </AccordionItem>
    <AccordionItem index={2}>
      <AccordionHeader>Header 3</AccordionHeader>
      <AccordionBody>Body 3 Content</AccordionBody>
    </AccordionItem>
  </Accordion>
);

export default App;

 

참고 사이트

 

React Design Patterns: Compound Component Pattern

How to avoid prop drilling and write elegant components with implicit state sharing

medium.com

728x90
728x90