React) 9. Composition

divedeepp·2022년 2월 4일
0

React

목록 보기
9/11

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


한 component에서 다른 component를 담기

어떤 component들은 어떤 자식 element가 들어올 지 미리 예상할 수 없는 경우가 있다. Sidebar나 Dialog같은 component들이 그 예시이다.

이러한 component에서는 특수한 children props을 사용하여 자식 element를 출력에 그대로 전달하는 것이 좋다.

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

이러한 방식으로 다른 component에서 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 element 안에 있는 것들이 FancyBorder component의 children props로 전달된다. FancyBorder component는 {props.children}을 <div> 안에 렌더링하므로 전달된 element들이 최종 출력된다.

또, 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 element는 단지 객체이기 때문에, 다른 데이터처럼 props로 전달할 수 있다.


특수화

때로는 어떤 component의 특수한 경우인 component를 고려해야할 수도 있다. 예를 들어, WelcomeDialog는 Dialog의 특수한 경우라고 할 수 있다.

React에서는 이 역시 합성을 통해 해결할 수 있다. 더 특수한 component가 일반적인 component를 렌더링하고 props를 통해 내용을 구성한다.

function Dialog(props) {
  return (
    <FancyBorder color="blue">
      <h1 className="Dialog-title">
        {props.title}
      </h1>
      <p className="Dialog-message">
        {props.message}
      </p>
    </FancyBorder>
  );
}

function WelcomeDialog() {
  return (
    <Dialog
      title="Welcome"
      message="Thank you for visiting our spacecraft!" />
  );
}

클래스에서도 동일하다

합성을 클래스로 정의된 component에서도 동일하게 적용된다.

function Dialog(props) {
  return (
    <FancyBorder color="blue">
      <h1 className="Dialog-title">
        {props.title}
      </h1>
      <p className="Dialog-message">
        {props.message}
      </p>
      {props.children}
    </FancyBorder>
  );
}

class SignUpDialog extends React.Component {
  constructor(props) {
    super(props);
    this.handleChange = this.handleChange.bind(this);
    this.handleSignUp = this.handleSignUp.bind(this);
    this.state = {login: ''};
  }

  render() {
    return (
      <Dialog title="Mars Exploration Program"
              message="How should we refer to you?">
        <input value={this.state.login}
               onChange={this.handleChange} />
        <button onClick={this.handleSignUp}>
          Sign Me Up!
        </button>
      </Dialog>
    );
  }

  handleChange(e) {
    this.setState({login: e.target.value});
  }

  handleSignUp() {
    alert(`Welcome aboard, ${this.state.login}!`);
  }
}
profile
더깊이

0개의 댓글