0

I am getting error of Cannot read property 'clickHandler' of undefined

var FilterableProductTable = React.createClass({
        render: function() {
            var rows = [];
            this.props.products.forEach(function(product) {
                if( product.Control == "" || product.Control == undefined) {
                   rows.push(<tr colSpan = "2"  key = {product.Field}><th>{product.Field}</th><td></td></tr>); //rows.push( < ProductHeader product = { product } key = { product.Field } /> );
                }
                else {                           
                    var ControlTag;
                    if(product.Control == "textarea") {
                        ControlTag = <span><textarea rows="4" cols="18" id={ product.id } title={ product.id }></textarea><i className="fa fa-pencil changeSetting" title="Change control"></i></span> 
                    }
                    else if(product.Control == "select") {
                        ControlTag = <span><select style={{width: '60%'}} id={ product.id } title={ product.id }><option></option></select><i className="fa fa-pencil changeSetting" title="Change control"></i></span> 
                    }
                    else {
                        ControlTag=<span><input type="text" id={ product.id } title={ product.id }/><i className="fa fa-pencil changeSetting" title="Change control"></i></span> 
                    }
                rows.push(<tr colSpan = "2" key = {product.Field}><th>{product.Field}</th><td onClick={ this.clickHandler }>{ControlTag}</td></tr>);                          // rows.push( < ProductRow product = { product }  key = { product.Field } />);
                }
            });                
            return ( <table className={'tagsTable'}><tbody>{rows}</tbody></table> )
        },
        clickHandler: function(e){ alert(); }
   });

is there something missing in code?

2 Answers 2

2

You are using forEach loop, so this inside loop will not be the component itself.

var FilterableProductTable = React.createClass({
        render: function() {
            var rows = [];
            var self = this; // <== new code
            this.props.products.forEach(function(product) {              
                // bunch of code..    
                // changed click to onClick={ self.clickHandler }
                rows.push(<td onClick={ self.clickHandler }>{ControlTag}</td>);
                // bunch of code..  
            });
        },
        clickHandler: function(e){ alert(); }
   });

Or set scope for forEach loop itself as suggested by Alexander T. Indeed i like it better than solution above

var FilterableProductTable = React.createClass({
        render: function() {
            var rows = [];
            this.props.products.forEach(function(product) {              
                // your code, without any modification
            }, this); // <== notice: this
        },
        clickHandler: function(e){ alert(); }
   });
Sign up to request clarification or add additional context in comments.

2 Comments

Damn, one minute too late.
@Medet Tleukabiluly it is not necessary use additional variable var self = this; because you can set this for forEach callback through second argument [].forEach(function () { ... }, this) - developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
1

It's because this is used inside a forEach function, so it refers to this function, not your React component. Use this little JS trick :

var self = this;

this.props.products.forEach(function(product) {
     <td onClick={ self.clickHandler }></td>
}

Comments

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.