Random Quote Machine with React: fetch() API problem

Hello,
I’m trying to understand what doesn’t work in my code. I followed the instructions in this post I'm having trouble {Random Quote Machine} (ReactJS), because the guy had exactly the same problem, but it doesn’t work yet.

I tried to console.log() many times. The ‘data’ when I fetch() comes, but I cannot store it in this.state.apiData (line 33).

Here is my codePen:

I also have two questions:

  1. is it better to use fetch() or something called ajax? Because I read a lot of topic where the people used ajax instead of fetch. I choosed fetch because I read also other tutorials, which explain fetch(), and I also learnt it on jS.

  2. If I would add a this.randomQuote into the constructor and not the this.state, would be the same thing, in general? I explain with the first Quote Machine I wrote: https://codepen.io/NicoCastel/pen/rNJeQad
    At the line 36 I declare this.obj, and at 49 I add it in the handleClick, and the result is that it works exactly like the this.state. Why should I use state and not the other? Only because of the this.setState method?

Open the console tab in the developer tools and you will see the error that is causing your problem:

“Uncaught (in promise) TypeError: this is undefined”

This error is referring to:

.then(function(data) {
    this.setState({
        apiData: data,
    });
});

I would recommend you add the following console.log right before the call to this.setState:

console.log('this = ', this);

The next step is to understand why the console.log gives you that result. Do you think you know the reason?

There are a few workarounds for this problem. You can save off this to another variable and then use that variable to access setState. That’s sort of the old hacky way to do it. The new way is to use async and await which will allow you to remain within the context of the class.

You can also make the .then() callback functions arrow functions.

1 Like

Good point. I’m so used to using async/await that I completely overlooked that solution :man_facepalming:

I’m trying to understand it. I had for example some problem to get the error in the console, since I’m not so used yet to use it. But, maybe the problem, is something about the componentDidMount(). I mean, usually I have to bind the method in the constructor like this.handleChange = this.handleChange.bind(this); but in this case I’m not doing it. But actually I’m not sure about this issue.

Ok than I tried it, but definitely I don’t understand why, with arrow function should work.

Thanks, I read also something, it’ll be the next step, as soon I understand the issue.

I suggest you also add

console.log('this = ', this);

at the very beginning of componentDidMount and I think you’ll see that this is defined in that method. So the problem isn’t with componentDidMount since this is working exactly as expected there.

The problem is that a “traditional” function called inside of the componentDidMount method doesn’t share the same this as componentDidMount. But when you use an arrow function then you override this behavior because arrow functions do not have their own this, they inherit this from their parent scope.

A great way to test this is the create a simple function inside of componentDidMount and then call it:

function testing() {
    console.log('testing this = ', this);
}
testing();

You’ll see that this is undefined because inside of the testing function this is not the same this as outside of it. Now do the same thing but with an arrow function:

const testingArrow = () => console.log('testingArrow this = ', this);
testingArrow();

You’ll see that this is exactly the same as the this for componentDidMount because arrow functions inherit this from their parent scope.

Don’t hesitate to experiment like this with your code. It’s a great way to learn. More details can be found at:

Understanding “this” in javascript with arrow functions

1 Like

Yes, I really have done it, but I didn’t get the problem. Thanks for the explaination :slight_smile: really helpful and sure, I’ll experiment.

This topic was automatically closed 182 days after the last reply. New replies are no longer allowed.