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

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

#1

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>
      );
    },
});

#2

ah nevermind someone already got it. Woot.


#3

.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)


#4

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.


#5

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)}/>);


#6

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.


#7

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


#8
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>
    );
  },
});

#9

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!


#10

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


#11

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

I cannot thank you enough.


#12

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.