React JS what is the proper way to bind a property to a function onClick?

I am trying to tie the key ( called “divkey” in my application) to an onClick event when the user clicks a square in the grid ( in order to change its color). Nothing I’ve tried seems to work.

The CodePen for this is here

handleClick: function(index, e){
  var test = this.state.currentData[index];
  console.log(test);
},

render: function() {
  var tempgrid = [],
     tempgridtotal2 = this.state.totalColumns * this.state.totalRows;
      for (var x = 0; x < tempgridtotal2; x++) {
        tempgrid.push(<ActionBox divkey={x} Name={x} divcolor={this.state.currentData[x]} onKlick={this.handleClick}/>);
      }


var ActionBox = React.createClass({ 
    render: function() {
      return(
        <div id="actionBox" index={this.props.divkey}  style={{backgroundColor:this.props.divcolor}} onClick={this.props.onKlick.bind(this.index)}  >
        </div>
      );
    },
});

ah nevermind someone already got it. Woot.

.bind needs a first argument of what to bind to. Try onClick={this.props.onKlick.bind(this, this.index)}

(assuming this is what you want the function bound to, otherwise you need to pass another components this into a prop)

That is one of the bizillion combinations of code I’ve tried this morning. Just tried it again just exactly as what you wrote. Still getting “undefned” in Console.

From the console.log inside the function?

It does not look like ActionBox has a state? Do you want this to refer to another component?

EDIT: Ah! I think I see the confusion. When you pass this.state.currentData[x] you are only passing the value, not a reference to the state. I believe you can do this:

tempgrid.push(<ActionBox divkey={x} Name={x} divcolor={this.state.currentData[x]} onKlick={this.handleClick.bind(this, divkey)}/>);

I was referring to the output from the console.log command that is in handleClick().

No, the component I am interested in is whichever ActionBox div gets clicked on by the user.

Yes, but the state is held in your other component, not in ActionBox. See my edit in my last post.

var ActionBox = React.createClass({ 
  render: function() {
    return(
      <div id="actionBox" index={this.props.divkey}  style={{backgroundColor:this.props.divcolor}} onClick={this.props.onKlick.bind(this, this.props.divkey)}  >
      </div>
    );
  },
});

Yup, tried that as well. I get your point and I tried that exact same thing earlier… But for some reason that approach actually breaks the entire application and nothing renders!

Oh, yeah, because that runs the function. Sorry. Try this:

tempgrid.push(<ActionBox divkey={x} Name={x} divcolor={this.state.currentData[x]} onKlick={this.handleClick} stateHolder={this}/>);

<div id="actionBox" index={this.props.divkey} style={{backgroundColor:this.props.divcolor}} onClick={this.props.onKlick.bind(this.props.stateHolder, this.props.divkey)} > </div>

EDIT: had this.index but jenovs post made me realize that is wrong as well, needs to be this.props.divkey

1 Like

“stateHolder={this}” ??? I ave not encountered this before in anything I have read, but holy moly THAT WORKS!!

I cannot thank you enough.

No problem! There is a proper way to do it, but I only know the ES6 version:

class MyComponent extends React.Component {
  constructor() {
    super();
    this.handleClick = this.handleClick.bind(this);
  }
  handleClick() {
    //do whatever
  }
}

This makes it so that anytime you call handleClick it is already bound. I don’t know how to call the constructor (suspect componentDidMount or componentWillMount would work too) without using the ES6 syntax, so I gave you sort of a hacky workaround :slight_smile:

Which means you could probably even do it like:

render: function() {
  var clickScript = this.handleClick.bind(this);
  return <Component onClickProp={clickScript} />
}

which is actually quite a bit better looking, now that I think of it.