0

I have the following working code:

fetchPost (id) {
var mainObject = {},
    toReturn = [],
    promises = [];
var that = this;

for(var i=id; i<10; i++) {
    promises.push(axios.get(`api/posts/${i}`));
}

axios.all(promises).then(function(results) {
    results.forEach(function(response) {
    toReturn.push(response.data);
    console.log("toReturn: " + toReturn);
    that.setState({ post: toReturn });
    });
});
}

but to get it working I had to add var that = this; so that that.setState would work.

Using this.setState would generate this error:

Uncaught (in promise) TypeError: Cannot read property 'setState' of undefined

So why do I have to use this hack that I don't understand to get this sample code to work? It doesn't make any sense to me.

kuwze
  • 371
  • 2
  • 12
  • 3
    I believe the that variable is scoped at the class/component level so you have access to anything at that level. But if you used an arrow function like (results) => { ...code} then you would get the this access to the class. I believe "this" in the promise would only refer to the promise's scope, and be able to see beyond that scope. – Dream_Cap Oct 12 '17 at 03:46
  • 1
    Where ever You are calling the fetchpost method You just need to bind "this" to the method so that the fetchpost method knows which "this" object you are referring to since you haven't bind "this" here so you are referring the plain "this" object not the one which contains react properties and methods – Vinit Raj Oct 12 '17 at 03:50
  • this is correct @dream_cap because he has used a declared function instead of a fat arrow function. a fat arrow function gains access to this from the parent whereas the scope of `this` is tto just the fetchPost function – patrick Oct 12 '17 at 03:50
  • The keyword `this` refers to the current context, unless it's been explicitly (using `bind`) or implicitly (using "fat arrow" functions) bound to a specific context. In your code, the `that` variable is set to the early value of `this`, so that this value of `this` can be referred to in a later context. It's an old (ugly) hack. – Thomas Hennes Oct 12 '17 at 03:56
  • I recommend to read [YDKJS - this & object prototypes](https://github.com/getify/You-Dont-Know-JS/blob/master/this%20&%20object%20prototypes/README.md#you-dont-know-js-this--object-prototypes) to learn how `this` works. It's pretty fundamental to JavaScript. [MDN - this](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this) is good too. – Felix Kling Oct 12 '17 at 04:01
  • Also related: [Why is JavaScript bind() necessary?](https://stackoverflow.com/q/41391288/218196) – Felix Kling Oct 12 '17 at 04:02

1 Answers1

1

I believe the that variable is scoped at the class/component level so you have access to anything at that level. But if you used an arrow function like (results) => { ...code} then you would get the this access to the class. I believe "this" in the promise would only refer to the promise's scope, and be able to see beyond that scope.

axios.all(promises).then((results) => { //changing to an arrow function where the arrow function does not bind it's own "this" scope
    results.forEach((response) => {
    toReturn.push(response.data);
    console.log("toReturn: " + toReturn);
    this.setState({ post: toReturn });
    });
});

Here is some more information about arrow functions and "this":

No binding of this: Until arrow functions, every new function defined its own this value (a new object in the case of a constructor, undefined in strict mode function calls, the base object if the function is called as an "object method", etc.). This proved to be annoying with an object-oriented style of programming.

Dream_Cap
  • 2,202
  • 1
  • 16
  • 29