Ad

React Passing Function To Child Not Working

- 1 answer

I have a react component that passes a function to a child component, and I bind it to onClick. But when I click I get an error:

this.props.beBad is not a function, this.props.beBad is not defined

it looks something like this:

var Dad = React.createClass({
  beBad: function(someInput) {
    alert('being bad ' + someInput);
  },
  render: function() {
    var Children = this.state.children.map(function(data, index) {
          return (
            <Child beBad={this.beBad} key={index}/>
          );
        });
        return (
            <div>
                {Children}
            </div>      
        );
  });

var Child = React.createClass({
  beBad: function() {
   this.props.beBad('some input');
  },
  render: function() {
    return(
     <div onClick={this.beBad}>
       be bad
     </div>
    );
  }
});
Ad

Answer

It doesn't look like this is what you expect. When using React.createClass, React will autobind the correct this IFF the call is at the top level of the function, so in this case it will autobind correctly:

render: function() {
  return (
   <div onClick={this.beBad}> // autobound
     be bad
   </div>
  );
}

But not here:

var Children = this.state.children.map(function(data, index) {
  return (
    <Child beBad={this.beBad} key={index}/> // `this` is not what you expect
  );
});
return (
  <div>
    {Children}
  </div>
);

The reason is because map is creating a new scope, and this is no longer what you'd expect, and React can't autobind it for you. You need to pass this around explicitly:

var Children = this.state.children.map(function(data, index) {
  return (
    <Child beBad={this.beBad.bind(this)} key={index}/> // bind `this`
  );
}, this); // pass `this`

Note: Seeing the other response, it is possible that React autobinds it for you inside the map, but in general I wouldn't rely on autobinding, explicit wins over implicit. Plus if you ever write React with ES6 classes it doesn't do autobinding.

Ad
source: stackoverflow.com
Ad