014 - Composition and Inheritance

I. Overview

React has a powerful composition model, and we recommend using composition instead of inheritance to reuse code between components.

1.1. Containment

Some components don't know their subcomponents ahead of time. This is especially common for components that represent likeSidebar or Dialoggeneric "boxes" .

It is recommended that these components use a special to children proppass child elements directly into their output:

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

This allows other components to pass arbitrary child objects to them via nested 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>
  );
}

Anything inside the <FancyBorder> JSX tag will be passed to the FancyBorder component as the children prop. Due toFancyBorder rendering {props.children}internals <div>, the passed element appears in the final output.

While this is less common, sometimes you may need multiple "holes" in a component. In this case, you can come up with your own convention instead of usingchildren :

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

React elements like <Contacts /> and <Chat /> are just objects, so you can pass them as props like any other data. This approach may remind you of "slots" in other libraries, but there are no restrictions on the props you can pass in React.

1.2/Specialization

Sometimes we think of components as "special cases" of other components. For example, we can say that a WelcomeDialog is a special case of Dialog.

In React, this can also be achieved through composition, where a more "specific" component renders a more "generic" component, configured with 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!" />
  );
}

Composition works equally well for components defined as 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}!`);
  }
}

What about inheritance?

At Facebook, we use React in thousands of components, and we haven't found any use cases that suggest creating a component inheritance hierarchy.

Props and composition give you all the flexibility you need to customize the appearance and behavior of your components in an unambiguous and safe way. Remember that components can accept arbitrary props, including primitive values, React elements or functions.

If you want to reuse non-UI functionality between components, we recommend unpacking it into a separate JavaScript module. Components can import it and use the function, object or class without extending it.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325194896&siteId=291194637
014