1

I need to pass props to a child component Product but i don't know what i'm missing here.

Parent Component:

var Products = React.createClass({
  getInitialState: function(){..},
  deleteProduct: function(){..},
  updateProduct: function(){..},
  render: function(){
    var products = _.map(this.state.products, function(product){
      return(
        <Product key={product.id} product={product} handleDeleteProduct={this.deleteProduct} handleEditProduct={this.editProduct} formData={this.props.formData}/>
      )
    });
  return (
    <table>
      <thead>
        <tr>
          <th>Name</th>
          <th>Quantity</th>
          <th>Price</th>
          <th colSpan="4">Actions</th>
        </tr>
      </thead>
      <tbody>
        {products}
      </tbody>
    </table>
  )
}
});

Child Component:

var Product = React.createClass({
 console.log(this); //props: handleDeleteProduct: undefined, handleEditProduct: undefined
 handleEdit: function() {
  e.preventDefault();
  data = {..};
  $.ajax({
    ..,
    success: (function(_this) {
      console.log(_this); //props: handleDeleteProduct: undefined, handleEditProduct: undefined
      return function(data) {
        _this.setState({
          edit: false
         });
        return _this.props.handleEditProduct(_this.props.product, data);
      };
    })(this)
  });
 }
});

I'm able to use key and product as a props inside the component but not this.props.handleDeleteProduct and this.props.handleEditProduct. I think may be i'm using the props inside the success callback of the $.ajax and then may be some thing related to async request. Not sure.

The error i'm getting is

Uncaught TypeError: _this.props.handleEditProduct is not a function

I'm not sure what i'm doing wrong here. I tried to loop directly in between <tbody> but still no luck. Also here i'm calling the functions like this.deleteProduct as a reference but not by function call. And if i do by calling by function then it is reporting execjs error.

I took this as a reference for looping inside JSX: loop inside React JSX

But no luck. Please help.

Community
  • 1
  • 1
Ahmad hamza
  • 1,816
  • 1
  • 23
  • 46

1 Answers1

1

You are passing handleEditProduct={this.editProduct}, when the function is called updateProduct in your parent component. Change it to handleEditProduct={this.updateProduct} and I'll bet it works

EDIT:

Since that didn't work, I looked a little harder and I think I see what the problem is. I'm fairly sure that _ doesn't autobind this like React.createClass does. So when you map over your products here:

var products = _.map(this.state.products, function(product){
      return(
        <Product key={product.id} product={product} handleDeleteProduct={this.deleteProduct} handleEditProduct={this.editProduct} formData={this.props.formData}/>
      )
    });

this is not set to your react element. Try keeping a reference to this before you map, explicitly bind this to your map function, or use ES6 arrow functions: https://babeljs.io/docs/learn-es2015/#arrows-and-lexical-this. The simplest way to achieve what you want would be to save this in a variable:

var self = this;
var products = _.map(this.state.products, function(product){
          return(
            <Product key={product.id} product={product} handleDeleteProduct={self.deleteProduct} handleEditProduct={self.editProduct} formData={self.props.formData}/>
          )
        });

You can also use bind to achieve the same effect: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind

taylorc93
  • 3,676
  • 2
  • 20
  • 34
  • I missed it but no luck. The error would be different if that was the case. – Ahmad hamza Jan 18 '16 at 20:15
  • Try console logging what `this` is outside of your ajax call and also what `_this` is inside of the success callback and post what those are – taylorc93 Jan 18 '16 at 20:17
  • I have posted the console.logs in the question just now. For quick reference they are both null: `//props: handleDeleteProduct: undefined, handleEditProduct: undefined` – Ahmad hamza Jan 18 '16 at 20:22
  • Can you please give me an example of how to give reference to `this`? I tried to put `this.editProduct` in a variable and used it in place of `this.editProduct` but no luck. – Ahmad hamza Jan 18 '16 at 20:33
  • Oh Nice. Very nice. Can you please elaborate how to identify such situations while writing the code? i have seen many times that people use `bind` after the function ends. – Ahmad hamza Jan 18 '16 at 20:40
  • 1
    `this` in javascript is determined entirely by what the "call-site" of the function is. In your case, you are calling `_.map`, so `this` will be set to `_`. If you want a much better explanation, this book is about as good as it gets:https://github.com/getify/You-Dont-Know-JS/tree/master/this%20%26%20object%20prototypes. Chapter 1 and 2 should cover everything you'd need to know – taylorc93 Jan 18 '16 at 20:44