2016-09-27 44 views
3

我正在为下拉菜单创建自定义React组件。我脑子里想的结构,使用该组件是的要求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成分,如果有,使用React.cloneElement克隆给定的DropdownTrigger组件并通过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

乍一看,它看起来像也许你可以只指定的''属性的'' ,而不是要求孩子通过。 –

+1

我最初尝试过,但我希望能够在我的''中使用自定义组件。也许我可以在''上有'triggerButton'属性,它需要一个React组件?这样我就不必循环孩子。 – Niekert

回答

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; 
相关问题