Brady
Brady

Reputation: 68

ReactJS component onClick not firing own function

I started this component with all the <th> hard coded in, but realized it would save me some time putting them in an array and calling it before render. But now the onClick event isn't firing.

I added in the <th id="category" onClick={this.handleClick}>test cat</th> to show that this still works. It seems that because the array I'm building is outside the return () it won't fire the onClick event.

Am I doing something wrong?

var Table = React.createClass({
    handleClick: function(sortid) {
        alert(sortid.target.id);
        this.props.sortClick(sortid.target.id);
    },
    render: function() {
        ...

        var columnDiv = this.props.columns.map(function(column, i) {
            return (
                <th id={column} key={i} onClick={this.handleClick}>
                    {column}
                </th>
            );
        });

        return (
            <table className="table table-hover">
                <thead>
                    <tr>
                        <th id="category" onClick={this.handleClick}>test cat</th>
                        {columnDiv}
                    </tr>
                </thead>
                <tbody>
                    {rows}
                </tbody>
            </table>
        );
    }
});

Upvotes: 3

Views: 964

Answers (2)

Markus-ipse
Markus-ipse

Reputation: 7396

The previous answer correctly points out what causes the problem, but you don't even have to use .bind() to get the correct value of this when using map(), as map has a second, optional parameter that allows you to specify the value to be used as this in the callback: arr.map(callback, [thisArg]);

var columnDiv = this.props.columns.map(function(column, i) {
    return (
        <th id={column} key={i} onClick={this.handleClick}>
            {column}
        </th>
    );
}, this);

or if you're writing in ES2015 (formerly known as ES6), for example using babel, you can just use a fat arrows, which will keep the 'this' value of the enclosing context, which means this would suffice:

var columnDiv = this.props.columns.map((column, i) => {
    return (
        <th id={column} key={i} onClick={this.handleClick}>
            {column}
        </th>
    );
});

Upvotes: 1

Mark Bolusmjak
Mark Bolusmjak

Reputation: 24419

When you say this.handleClick inside your mapped function, this refers to the function itself. Not your class.

You need to bind your function, or get a reference to handleClick before you map.

e.g.

    var columnDiv = this.props.columns.map(function(column, i) {
        return (
            <th id={column} key={i} onClick={this.handleClick}>
                {column}
            </th>
        );
    }.bind(this));

Upvotes: 0

Related Questions