Edit on GitHub

Composição vs Herança

React tem um modelo poderoso de composição, e recomedamos usar composição ao invés de herança para reusar código entre componentes.

Nesta seção, vamos considerar vários problemas que novos desenvolvedores em react geralmente resolvem com herança, e mostramos como podemos resolver com composição.

Conteinerização #

Alguns componentes não conhecem seus filhos antes do tempo. Isto é especialmente comum para componentes como Sidebar ou Dialog que representam "caixas" genéricas.

Recomendamos que esses componentes usem a propriedade especial children para passar elementos filhos diretamente para sua saída:

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

Isso permite que outros componentes passem filhos arbitrários para eles com JSX aninhado:

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

Teste este código no CodePen.

Qualquer coisa dentro da tag <FancyBorder> é passado para dentro do componente FancyBorder como uma propriedade children. Uma vez que FancyBorder renderiza {props.children} dentro de uma <div>, os elementos passados aparecem na saída final.

Enquanto isso é menos comum, às vezes você pode precisar de múltiplos "buracos" em um componente. nesses casos você pode vir usar suas própria convenção ao invés de usar 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 />
      } />
  );
}

Teste este código no CodePen.

Elementos React como <Contacts /> e <Chat /> são apenas objetos, então você pode passá-los como propriedades como qualquer outro dado.

Especialização #

As vezes pensamos em componentes como sendo "casos especiais" de outros componentes. Por exemplo, nós podemos dizer que um WelcomeDialog é um caso especial de Dialog.

Em React, isto também é alcançado pela composição, onde um componente mais "específico" renderiza um mais "genérico" e configura-o com as propriedades:

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

Teste este código no CodePen.

Composição funciona igualmente bem para componentes definidos como classes:

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

Teste este código no CodePen.

Então, e sobre herança? #

No Facebook, usamos React em milhares de componentes e não encontramos nenhum caso de uso onde recomendamos a criação de componentes com hierarquias de herança.

Propriedades e composição nos dão toda a flexibilidade que precisamos para customizar o visual e o comportamento de um componente de forma explícita e segura. Lembre-se que componentes podem aceitar propriedades arbitrárias, incluindo valores primitivos, elementos React ou funções.

Se você quer reusar funcionalidades não visíveis entre componentes, nós sugerimos extrai-lá para um módulo JavaScript separado. Os componentes podem importá-lo e usar essa função, objeto ou classe, sem extendê-lo.