简体   繁体   English

在React Component中要求某些类型的子项

[英]Require children of certain type in React Component

I am creating a custom React Component for a Dropdown menu. 我正在为下拉菜单创建自定义React组件。 The structure I had in mind to use this component was something among the lines of 我想到的使用这个组件的结构是其中的一部分

<Dropdown>
  <DropdownTrigger> // The button that triggers the dropdown to open or close
    open me
  </DropdownTrigger>
  <DropdownButton> // A button inside the dropdown
    Option 1
  </DropdownButton>
</Dropdown>

The way I wanted to implement this, is by having the Dropdown component check if there is a DropdownTrigger component in its children, and if there is, clone the given DropdownTrigger component using React.cloneElement and pass an onClick property, that calls a state update on the Dropdown component. 我想要实现它的方法是让Dropdown组件检查其子React.cloneElement是否有DropdownTrigger组件,如果存在,则使用React.cloneElement克隆给定的DropdownTrigger组件并传递onClick属性,该属性调用状态更新在Dropdown组件上。

Small code snippet of Dropdown.js Dropdown.js小代码片段

  import DropdownTrigger from './DropdownTrigger';

  _toggleDropdown () {
    this.setState({
      isOpen: !this.state.isOpen
    });
  }


  _renderTriggerButton () {
    const triggerChild = this.props.children.find(child => child.type === DropdownTrigger);
    return React.cloneElement(triggerChild, {
      ...triggerChild.props,
      onClick: () => this._toggleDropdown()
    });
  }

Is this a correct approach and if so, what would be the cleanest/nicest possible way to validate the Dropdown component has a DropdownTrigger as child. 这是一种正确的方法,如果是这样,那么验证Dropdown组件的最干净/最好的方法是将DropdownTrigger作为子级。 As this means a developer always has to include a DropdownTrigger as child of the Dropdown component, I would like to have a nice way to tell developer they should pass a <TriggerButton> component as child of the dropdown. 因为这意味着开发人员总是必须包含DropdownTrigger作为Dropdown组件的子代,我想有一个很好的方法告诉开发人员他们应该将<TriggerButton>组件作为下拉列表的子项传递。

I'm also open for suggestions about changes in the structure. 我也愿意接受有关结构变化的建议。 Thanks! 谢谢!

Use React.cloneElement to pass additional properties to child components. 使用React.cloneElement将其他属性传递给子组件。 In combination with instanceof you can do exactly what you want. 结合instanceof,您可以完全按照自己的意愿行事。


It could be something along the lines... 它可能是一些东西......

import React from 'react';
import DropdownTrigger from './DropdownTrigger';

class DropDown extends React.Component {
  constructor(props) {
    super(props);
  }

  ...

  render() {
    return (
      <div>
        {React.Children.map(this.props.children, child => {
          const additionalProps = {}
          // add additional props if it's the DropdownTrigger
          if (child instanceof DropdownTrigger) {
            additionalProps.toggleDropDown = () => { } ...
          }

          return React.cloneElement(child, additionalProps);
        })}
      </div>
    );
  }
}

export default DropDown;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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