How to use fetch() API in React to setState
It is saying setState
is undefined because you're accessing it in the wrong context. You can either, convert the function into an arrow function or bind it to the right context. Here is an article as to When and why do we bind this to the React component method.
In your code, the change that can be made is either binding it
.then(function(jsonStr){
this.setState({apiInfo: jsonStr});
console.log(jsonStr);
}.bind(this));
or using arrow function
.then((jsonStr)=>{
this.setState({apiInfo: jsonStr});
console.log(jsonStr);
});
Your error message is telling you exactly what the problem is:
unable to setState of undefined
So you're trying call setState
as a method of an object that doesn't exist at that point. As a property of what object are you trying to call setState
as a method?
this.setState({apiInfo: jsonStr});
Yes, it's your this
that's the problem. At the point that you're trying to call it - i.e. inside a .then()
of a fetch
call - this
is actually undefined. You can see this in the Chrome Devtools:
I'm afraid that this
is a slippery customer in JavaScript; its value can (and does) change depending upon the current context of your app.
There's several ways you can workaround this. One slightly clunky (but it works!) way is to capture your this
value before you enter your .fetch() call, and assign it to another variable. You'll often see that
or self
variables used for this purpose, but they're just conventions. You can call the variable what you like.
Here's how I've reworked your componentDidMount() method capturing this
to that
, and calling that
inside the .then()
:
componentDidMount() {
const that = this;
fetch("https://fcctop100.herokuapp.com/api/fccusers/top/recent")
.then(function(response) {
return response.json();
})
.then(function(jsonData) {
return JSON.stringify(jsonData);
})
.then(function(jsonStr) {
that.setState({ apiInfo: jsonStr });
console.log(jsonStr);
});
}
If you're comfortable using arrow functions, then another way is to replace your "normal" function call with one, like so:
.then(jsonStr => {
this.setState({ apiInfo: jsonStr });
console.log(jsonStr);
});
An arrow function's this
is always the this
that its parent defined.