[英]How to use fetch() API in React to setState
I'm trying to write a component in React that will use the fetch() API to get data from a website, then use setState to set a state equal to the data, and then finally render the data.我正在尝试在 React 中编写一个组件,该组件将使用 fetch() API 从网站获取数据,然后使用 setState 设置与数据相等的状态,最后呈现数据。 My code looks like this:我的代码如下所示:
import React from 'react';
export default class Test extends React.Component {
constructor(props){
super(props);
this.state = {apiInfo: 'default'};
}
componentDidMount(){
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){
this.setState({apiInfo: jsonStr});
console.log(jsonStr);
});
}
render(){
return(
<tr>
<td>{this.state.apiInfo}</td>
</tr>
);
}
}
However, this results with an error saying I'm unable to setState of undefined.但是,这会导致错误提示我无法设置未定义的状态。 I end up rendering 'default' on my HTML.我最终在我的 HTML 上呈现“默认”。 What exactly am I doing wrong here?我到底做错了什么?
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.因此,您正在尝试将setState
作为当时不存在的对象的方法进行调用。 As a property of what object are you trying to call setState
as a method?作为什么对象的属性,您试图将setState
作为方法调用?
this.setState({apiInfo: jsonStr}); this.setState({apiInfo: jsonStr});
Yes, it's your this
that's the problem.是的,这是你this
这就是问题所在。 At the point that you're trying to call it - ie inside a .then()
of a fetch
call - this
is actually undefined.在您尝试调用它时——即在fetch
调用的.then()
内—— this
实际上是未定义的。 You can see this in the Chrome Devtools:您可以在 Chrome Devtools 中看到这一点:
I'm afraid that this
is a slippery customer in JavaScript;恐怕this
是 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.一种稍微笨拙(但它有效!)的方法是在您输入 .fetch() 调用之前捕获您的this
值,并将其分配给另一个变量。 You'll often see that
or self
variables used for this purpose, but they're just conventions.您会经常看到用于此目的的that
或self
变量,但它们只是约定。 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() 方法,将this
捕获到that
,并在.then()
调用that
:
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.箭头函数的this
始终是其父定义的this
。
It is saying setState
is undefined because you're accessing it in the wrong context.它说setState
未定义,因为您在错误的上下文中访问它。 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. 这是一篇关于何时以及为什么将其绑定到 React 组件方法的文章。
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);
});
componentDidMount() {
fetch('https://fcctop100.herokuapp.com/api/fccusers/top/recent')
.then(response => response.json())
.then(data => this.setState({ apiInfo: data }));
}
In your render function you cannot just do this.state.apiInfo
.在您的渲染函数中,您不能只执行this.state.apiInfo
。 This data is an array of objects, each object has keys like username
img
and more.这个数据是一个对象数组,每个对象都有username
img
等键。 You can see that if you console.log(this.state.apiInfo)
inside the render
function and outside the return
.您可以看到,如果在render
函数内部和return
外部的console.log(this.state.apiInfo)
。
To access and display the each object inside of the arrays values you can map
through your apiInfo
array.要访问和显示数组值中的每个对象,您可以通过apiInfo
数组进行map
。
render() {
const { apiInfo } = this.state;
apiInfo && console.log(apiInfo.map(item => item.img));
return (
<div>
{apiInfo &&
apiInfo.map(item => <div> {item.img} </div> )}
</div>
);
}
The native fetch API that comes with the browser uses JavaScript promises to resolve the asynchronous response.浏览器附带的原生 fetch API 使用 JavaScript 承诺来解决异步响应。
When the data is fetched successfully, it will be stored in the local state with React's this.setState() method.当数据获取成功时,它会通过 React 的 this.setState() 方法存储在本地状态中。 Then the render() method will trigger again and you can display the fetched data.然后 render() 方法将再次触发,您可以显示获取的数据。
Arrow functions were introduced in ES6, and an arrow function does not have its own context and will instead use the same this
as the context in which it was defined. ES6 中引入了箭头函数,箭头函数没有自己的上下文,而是使用与定义它的上下文相同的this
。 We can use this fact and pass in an arrow function to the callback.我们可以使用这个事实并将箭头函数传递给回调。
this
refers to the object which calls the function. this
指的是调用该函数的对象。this
however arrow functions does not ( this
here refers to the outside context ie, what this
is outside the function.).每个普通函数都有自己的this
但箭头函数没有(这里this
指的是外部上下文,即this
在函数之外的内容。)。So the possible solutions are所以可能的解决方案是
componentDidMount = () => {
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){
this.setState({apiInfo: jsonStr});
console.log(jsonStr);
});
}
this
in some other variable earlier and pass it as argument.保存this
在以前其他一些变量,并传递作为参数。this
to the function this
绑定到函数https://reactjs.org/docs/handling-events.html https://reactjs.org/docs/handling-events.html
Write the fetch code into separate method, then you will be able to call this.setState({}) inside the ".then(..)" statement after adding a bind to the new function inside the constructor.将fetch代码写入单独的方法中,然后在构造函数内部添加绑定到新函数后,您将能够在“.then(..)”语句中调用this.setState({})。
Example:示例:
constructor(props){
super(props)
...
this.myFunc = this.myFunc.bind(this)
}
myFunc = () => {
fetch('...')
.then(response => response.json())
.then(data => this.setState({ apiInfo: data }));
}
componentDidMount() {
this.myFunc()
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.