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

时间:2016-09-27 14:44:55

标签: javascript reactjs

我正在为下拉菜单创建自定义React组件。我想到的使用这个组件的结构是

的内容
<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>

我想要实现这一点的方法是让Dropdown组件检查其子组件中是否有DropdownTrigger组件,如果有,则克隆给定的DropdownTrigger组件使用React.cloneElement并传递onClick属性,该属性会调用Dropdown组件的状态更新。

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

这是一种正确的方法,如果是这样,那么验证Dropdown组件的最干净/最好的方法是DropdownTrigger为子。因为这意味着开发人员必须包含DropdownTrigger作为Dropdown组件的子项,我想有一个很好的方法告诉开发人员他们应该传递一个<TriggerButton>组件作为子组件下拉列表。

我也愿意接受有关结构变化的建议。谢谢!

1 个答案:

答案 0 :(得分:2)

使用React.cloneElement将其他属性传递给子组件。结合instanceof,您可以完全按照自己的意愿行事。

这可能是一线......

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;