3

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

2 Answers 2

1

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>
    );
});
Sign up to request clarification or add additional context in comments.

Comments

0

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

4 Comments

Thank you! I'm still learning about the bind command but remember setting this in the past. In case this helps anyone in the future, this is the small modification that fixed it: }.bind(this));
The meaning of this is not entirely intuitive in Javascript. .bind(this) roughly means: take the this I have now, and make is so in the function, when I say this, it's the same thing. It's important because inside a function, this usually refers to the function itself.
.map doesn't provide this by default, so it defaults to the global object, or undefined in strict mode. You can test it with: [1].map(function(){return this})
You don't even have to use bind, you can just pass this as the last argument to the map function: columns.map(function() {...}, this) or if you're writing in ES2015 (formerly known as ES6) you can just use a fat arrow, which will keep the

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.