Kucl Stha
Kucl Stha

Reputation: 585

How to pass function from parent to a child in react?

I have a Dropdown component which uses onClick={this.openDrop} on a button located inside the component. The component is as following:

import React, { Component } from 'react'

export default class Dropdown extends Component {
  constructor(){
    super()

    this.state ={
      subMenu: ''
    }

    this.openDrop = this.openDrop.bind(this)
    this.closeDrop = this.closeDrop.bind(this)
  }

  closeDrop(){
    this.setState({subMenu: ''}, ()=>{
      document.removeEventListener('click', this.closeDrop)
    })
  }

  openDrop(e){
    e.preventDefault()
    this.setState({subMenu: 'open'}, ()=>{
      document.addEventListener('click', this.closeDrop)
    })
  }

  render(){
    return (
      <div className={`btn-group ${this.state.subMenu}`}>
        <button type="button" className="btn btn-default dropdown-openDrop" onClick={this.openDrop}>
          Action <span className="caret"></span>
        </button>
        <ul className="dropdown-menu">
          <li><a href="#">Action</a></li>
          <li><a href="#">Another action</a></li>
          <li><a href="#">Something else here</a></li>
          <li role="separator" className="divider"></li>
          <li><a href="#">Separated link</a></li>
        </ul>
      </div>
    )
  }
}

I want to get the inner content as a props.children as following:

  render(){
    return (<div className={`btn-group ${this.state.subMenu}`}>{this.props.children}</div>
  }

And use it as following

<Dropdown>
    <button type="button" className="btn btn-default dropdown-openDrop">
          Action <span className="caret"></span>
        </button>
        <ul className="dropdown-menu">
          <li><a href="#">Action</a></li>
          <li><a href="#">Another action</a></li>
          <li><a href="#">Something else here</a></li>
          <li role="separator" className="divider"></li>
          <li><a href="#">Separated link</a></li>
        </ul>
</Dropdown>

But the problem is that I cannot pass the onClick={this.openDrop} into the button.

How can I pass the onClick={this.openDrop}?

Upvotes: 1

Views: 1707

Answers (2)

Dipesh Wagle
Dipesh Wagle

Reputation: 270

You can iterate over all the children of a component using React.Children. And we can clone every child with addition props with React.clone(element,{ additionalProps }). Here we check if the child is a button and add onClick props to it.

render() {
    const {children} = this.props;

    var childrenWithProps = React.Children.map(children, child => {
      if (child.type == "button") {
        return React.cloneElement(child, { onClick: this.openDrop })
      } else {
        return React.cloneElement(child)
      }
    });

    return (
      <div className={`btn-group ${this.state.subMenu}`}>{childrenWithProps}</div>
    );
  }

Upvotes: 1

Yash
Yash

Reputation: 171

You need to pass the a props to your inner component so that when that props will received using componentWillReceiveProps then you can set your state, just an eg.

constructor() {
    this.state={
        toggle: false
   }  
}
toggleDropdown(){
    this.setState({toggle: true})
}
<Dropdown toggle={this.state.toggle}>
    <button type="button" onClick={this.toggleDropdown()} className="btn btn-default dropdown-openDrop">
      Action <span className="caret"></span>
    </button>
    <ul className="dropdown-menu">
      <li><a href="#">Action</a></li>
      <li><a href="#">Another action</a></li>
      <li><a href="#">Something else here</a></li>
      <li role="separator" className="divider"></li>
      <li><a href="#">Separated link</a></li>
    </ul>
</Dropdown>

You've to pass toggle prop to your dropdown component, Now within your Dropdown component you will receive that props and when it'll true you can setState of your submenu, just an idea, there are other many ways to do it.

Upvotes: 0

Related Questions