如何在 React 中使用 fetch() API 来设置状态

2022-01-20 00:00:00 reactjs fetch javascript promise

我正在尝试在 React 中编写一个组件,该组件将使用 fetch() API 从网站获取数据,然后使用 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. 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>
        );
    }
}

但是,这会导致错误提示我无法设置未定义的状态.我最终在我的 HTML 上呈现默认".我到底做错了什么?

However, this results with an error saying I'm unable to setState of undefined. I end up rendering 'default' on my HTML. What exactly am I doing wrong here?

推荐答案

你的错误信息告诉你到底是什么问题:

Your error message is telling you exactly what the problem is:

无法设置未定义的状态

因此,您尝试调用 setState 作为当时不存在的对象的方法.作为什么对象的属性,您试图将 setState 作为方法调用?

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});

this.setState({apiInfo: jsonStr});

是的,问题出在你的 this 上.在您尝试调用它时 - 即在 fetch 调用的 .then() 内部 - this 实际上是未定义的.您可以在 Chrome Devtools 中看到这一点:

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:

恐怕 this 是 JavaScript 中的滑手;它的值可以(并且确实)根据您应用的当前上下文而改变.

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.

有几种方法可以解决此问题.一种稍微笨拙(但它有效!)的方法是在您输入 .fetch() 调用之前捕获您的 this 值,并将其分配给另一个变量.您经常会看到用于此目的的 thatself 变量,但它们只是约定.你可以随意调用变量.

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.

以下是我如何重新设计您的 componentDidMount() 方法,将 this 捕获到 that,并在 .then 中调用 that():

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);
});

箭头函数的 this 始终是其父函数定义的 this.

An arrow function's this is always the this that its parent defined.

相关文章