简体   繁体   中英

What's the React way for a transclusion design pattern?

I want to encapsulate as much as I can. Let's say we are using a CSS framework that has a modal, and we want to componentize it. This would allow us to centralize all instances of the code, so if we want to change the modal then we only have to change it in this component.

<Modal
    header={
        "Title"
    }
    body={
        <div>hello</div>
    }
    footer={
        <button>Push me</button>
    }
    />

Behind the scenes, it looks something like this:

const Modal = () => {
    return <div className="modal">
        <div className="modal-head">
            {this.props.head}
        </div>
        <div className="modal-body">
            {this.props.body}
        </div>
        <div className="modal-footer">
            {this.props.footer}
        </div>
    </div>
}

I don't particularly find anything wrong with this design pattern and I think it achieves exactly what I want. However, I suspect there might be a more "proper" way.

There is nothing wrong with passing components through props, except that a component should be unconventionally formatted in order to be readable, also components that are passed through props are more deeply indented this way:

<Modal
    header={
        "Title"
    }

A common approach is to just provide presentational components for each part:

const ModalHeader = props => <div className="modal-headerbody">{props.children}</div>;

Parent component can be as restrictive as needed with children:

class Modal extends Component {
  static Header = ModalHeader;

  render() {
    return (
      <div className="modal">
        {this.props.children.find(({ type }) => type === ModalHeader)}
        ...
      </div>
    );
  }
}

Also can host children components as static properties:

<Modal>
  <Modal.Header>...</Modal.Header>
</Modal>

There are two major patterns for designing components based on React Composition Model :

  1. Some components don't know their children ahead of time. This is especially common for components like Sidebar or Dialog that represent generic “boxes”

Example:

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

function WelcomeDialog() {
  return (
    <FancyBorder color="blue">
      <h1 className="Dialog-title">
        Welcome
      </h1>
      <p className="Dialog-message">
        Thank you for visiting our spacecraft!
      </p>
    </FancyBorder>
  );
}
  1. sometimes you might need multiple “holes” in a component. In such cases you may come up with your own convention instead of using children

Example:

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

the second pattern is exactly what you wrote in your question.

for your example, it seems better for you to use first design pattern

Refrence : https://reactjs.org/docs/composition-vs-inheritance.html

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM