Programming

[TIL] React Compound Components Pattern (design pettern)

jay-dev 2023. 9. 14. 00:31

컴파운드 컴포넌트 패턴

간단하게 말하면 내부 상태를 공유하는 컴포넌트

 

코드

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

const ToggleContext = createContext();

const Toggle = ({ children }) => {
  const [on, setOn] = useState(false);
  const toggle = () => setOn(!on);

  return <ToggleContext.Provider value={{ on, toggle }}>{children}</ToggleContext.Provider>;
};

const On = ({ children }) => {
  const { on } = useContext(ToggleContext);
  return on ? children : null;
};

const Off = ({ children }) => {
  const { on } = useContext(ToggleContext);
  return on ? null : children;
};

const Button = () => {
  const { toggle } = useContext(ToggleContext);
  return <button onClick={toggle}>토글</button>;
};

Toggle.On = On;
Toggle.Off = Off;
Toggle.Button = Button;

const App = () => {
  return (   
      <Toggle>
        <Toggle.On>켜기</Toggle.On>
        <Toggle.Off>끄기</Toggle.Off>
        <Toggle.Button />
      </Toggle>
  );
};

 

Toggle 컴포넌트에는 세가지 기능

  • 켜기
  • 끄기
  • 메뉴를 토글할 수 있는 버튼

 

 

Button 컴포넌트가 ToggleContext Provider에 접근할 수 있도록 해당 컴포넌트는 Toggle 의 자식 컴포넌트로 렌더링해야 한다. 따라서 단순히 자식 컴포넌트로 렌더링 하면 되지만. 여기서는 Toggle 컴포넌트의 Static property로 만들고 있다.

Toggle.On = On;
Toggle.Off = Off;
Toggle.Button = Button;

이렇게 하면 Toggle 컴포넌트를 사용하는 쪽에서 Button이 필요한 경우 그냥 Toggle 컴포넌트만 import하면 된다.

import React from 'react'
import { Toggle } from './Toggle'

export default function ToggleMenu() {
  return (
    <Toggle>
      <Toggle.Button />
    </Toggle>
  )
}

 

장점

재사용성: On / Off 같은 작은 부품들은 다른 상황에서도 쓸 수 있음
유연성: 컴파운드 패턴을 사용하면 작은 부품들을 자유롭게 조합 가능, 여러 가지 다른 기능을 쉽게 추가
코드의 명확성: 각 부품이 하는 일이 명확해서, 코드를 읽거나 이해하기 쉬움
유지보수: 나중에 코드를 고치거나 업데이트할 때도 각 부품만 따로 고칠 수 있음

단점

복잡, 러닝 커브 높을 수 있음

간단한 기능에 적용하기는 오히려 복잡해질 수 있음

 

 

Compound Components Pattern을 활용한 대표적인 리액트 라이브러리
[Material UI] [Chakra UI]