React는 강력한 합성 모델을 가지고 있으며, 상속 대신 합성을 사용하여 컴포넌트 간에 코드를 재사용하는 것이 좋다.

이번 문서에서는 React를 처음 접한 개발자들이 종종 상속으로 인해 부딪히는 몇 가지 문제들과 합성을 통해 이러한 문제를 해결하는 방법을 살펴본다.


컴포넌트에서 다른 컴포넌트를 담기

어떤 컴포넌트들은 어떤 자식 엘리먼트가 들어올 지 미리 예상할 수 없는 경우가 있다. 범용적인 '박스' 역할을 하는 Sidebar 혹은 Dialog와 같은 컴포넌트에서 자주 볼 수 있다.

이러한 컴포넌트에서는 특수한 children prop을 사용하여 자식 엘리먼트를 출력에 그대로 전달하는 것이 좋다.

function FancyBorder(props) {
  return (
    <div className={'FancyBorder FancyBorder-' + props.color}>
      ***{props.children}***
    </div>
  );
}

이러한 방식으로 다른 컴포넌트에서 JSX를 중첩하여 임의의 자식을 전달할 수 있다.

function WelcomeDialog() {
  return (
    <FancyBorder color="blue">
      ***<h1 className="Dialog-title">
        Welcome
      </h1>
      <p className="Dialog-message">
        Thank you for visiting our spacecraft!
      </p>***
    </FancyBorder>
  );
}

<FancyBorder> JSX 태그 안에 있는 것들이 FancyBorder 컴포넌트의 children prop으로 전달 된다. FancyBorder{props.children}<div> 안에 렌더링하므로 전달된 엘리먼트들이 최종 출력된다.

흔하지는 않지만 종종 컴포넌트에 여러 개의 "구멍"이 필요할 수도 있다. 이런 경우에는 children 대신 자신만의 고유한 방식을 적용할 수도 있다.

function SplitPane(props) {
  return (
    <div className="SplitPane">
      <div className="SplitPane-left">
        ***{props.left}***
      </div>
      <div className="SplitPane-right">
        ***{props.right}***
      </div>
    </div>
  );
}

function App() {
  return (
    <SplitPane
      left={
        ***<Contacts />***
      }
      right={
        ***<Chat />***
      } />
  );
}

<Contacts /><Chat />같은 React 엘리먼트는 단지 객체이기 때문에 다른 데이터처럼 prop으로 전달할 수 있다. 이러한 접근은 다른 라이브러리의 "슬롯 (slots)"과 비슷해보이지만 React에서 prop으로 전달할 수 있는 것에는 제한이 없다.