IT

[영어로 배우는 React] 11. 구성 vs 상속

생각파워 2022. 4. 28. 17:03

공식 사이트 : https://reactjs.org/docs/composition-vs-inheritance.html

 

 

리액트는 파워풀한 구성 모델을 가지고 있습니다. 그래서 컴포넌트들 사이에 코드 재사용을 위해 상속을 사용하기보다는 구성을 사용하는 것을 추천합니다. 

이번 섹션에서는 리액트를 처음 접하는 개발자가 종종 상속에 도달하는 문제를 고려해보고, 이를 구성으로 어떻게 해결하는지를 보여줄 것입니다. 

 

 

containment

몇몇 컴포넌트들은 자식을 미리 알지 못합니다. 이것은 특히 Sidebar나 Dialog와 같이 일반적인 박스를 표현하는 컴포넌트에 공통적으로 나타납니다. 리액트에서는 컴포넌트가 자식 앨리먼트를 직접 그들의 출력으로 전달하기 위해서, 특별한 자식  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 컴포넌트 안으로 전달됩니다. {props.children}과 같은 방식으로 사용할 수 있습니다. FancyBorder가 <div> 내에서 {props.children}을 랜더링하기 때문에 전달된 앨리먼트들은 최종 결과에 나타나게 됩니다. 

 

일반적이지 않은 상황에서, 가끔 컴포넌트에 여러 개의 구멍이 필요할 수 있습니다. 이런 경우에 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 />과 같은 리액트 앨리먼트는 단지 오브젝트입니다. 그래서 다른 데이터들처럼 props로 전달할 수 있습니다. 이 접근방법은 다른 라이브러리의 슬롯을 생각나게 할 수 있지만, 리액트에서는 어떤 값도 props로 전달할 수 있습니다. 

 

 

세분화

가끔 다른 컴포넌트가 세분화된 케이스로 존재하는 것에 대해 생각해봅니다. 예를 들면, 우리는 WelcomeDialog가 Dialog의 세분화된 케이스라고 말할 수도 있습니다. 

리액트에서 이것은 특정한 구성요소가 일반적인 구성요소를 랜더링 하고, 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!" />  
  );
}

클래스로 선언된 컴포넌트도 똑같이 작동합니다.

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}!`);
  }
}

 

그래서 상속은 어떻습니까?

facebook에 우리는 수천 개의 리액트 컴포넌트를 사용했습니다. 그리고 우리가 상속계층 컴포넌트를 추천하는 어떤 케이스도 발견할 수 없었습니다. props와 구성은 명시적이고 안전한 방법으로 컴포넌트의 모양과 행동을 커스터마이징 하는데 유연함을 줍니다. 컴포넌트가 기본값, 리액트 앨리먼트, 함수를 포함하여, 임의적인 props를 받을 수 있다는 것을 기억하세요.

컴포넌트 사이에 UI가 아닌 기능적인 재사용이 필요하다면, 우리는 그 부분을 자바스크립트 모듈로 분리할 것을 제안합니다. 컴포넌트는 자바스크립트 모듈을 import 해서 함수와 객체, 클래스를 확장 없이 사용할 수 있을 겁니다. 

반응형