Passing a child component as prop when that child needs to trigger parent's state?


#1

I have a modal that is opened by a button click. I want to use it in different places with different types of buttons. I understand I can pass components into the parent, but what about when those components need to trigger the parent’s state?

const modalButtonOne = () => (
<CircleButton />
);

const modalButtonTwo = () => (
<SquareButton />
);

export class Modal extends React.Component {

   constructor(props) {
    super(props);
    this.handleClose = this.handleClose.bind(this);
    this.handleOpen = this.handleOpen.bind(this);
    this.state = {
      open: false,
    };      
  }
handleOpen() {
    console.log('this ran')
    this.setState({open: true});
}

handleClose() {
    this.setState({open: false});
}
render(){
return <div>
  {this.props.modalButton}
  <Modal>
  </Modal>
</div>
}
);

( of course the modal component above is a stateless component for brevity, but imagine its an es6 class with a state object that has a ‘open boolean’)

Then I could have a modal that is triggered by either a circle button or a square button:

<Modal 
  modalButton={<CircleButton onTouchTap={this.handleOpen} />} 
/>

but how to I have 's onClick trigger the ‘open’ state of the parent modal?


#2

The parent already has that child prop!

If the child has a prop, then it is because its parent provided that prop to the child! Why do you want the child to pass back the prop to the parent, while the parent obviously already has that prop?


#3

See http://stackoverflow.com/questions/22639534/pass-props-to-parent-component-in-react-js


#4

You can do some really cool stuff with passing around child components. See https://github.com/dbx834/sandbox/blob/master/packages/sandbox-lib-duplicate/lib/container-components/Tangle.jsx#L289:L372. There’s nesting upto 3 levels, and props are ‘managed’ only once.


#5

I updated my pseudo code to better explain.

I need the buttons to trigger this.handleOpen


#6

These are exactly the things React takes care of for you. See https://facebook.github.io/react/blog/2013/07/02/react-v0-4-autobind-by-default.html and https://facebook.github.io/react/docs/thinking-in-react.html

Here’s a simple example of what you want done.

class Parent extends React.Component {
  constructor(props) {
    super(props)
    this.handler = this.handler.bind(this)
  }

  handler(e) {
    e.preventDefault()
    this.setState({
      someVar: someValue
    })
  }

  render() {
    return <Child handler = {this.handler} />
  }
}

class Child extendes React.Component {
  render() {
    return <Button onClick = {this.props.handler}/ >
  }
}

PS: For you, the child is the Square or Circle button and the parent is the modal.

I hope that helps.