简体   繁体   English

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

[英]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 中看到这一点:

Chrome Devtools 显示 this=undefined 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.您会经常看到用于此目的的thatself变量,但它们只是约定。 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指的是调用该函数的对象。
  • every normal function has its own 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所以可能的解决方案是

  • Use Arrow function使用箭头功能
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);
            });
}
  • save this in some other variable earlier and pass it as argument.保存this在以前其他一些变量,并传递作为参数。
  • Bind 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.

相关问题 如何在React中的表单提交上使用setState和访存API? - How to use setState with fetch API on form submit in React? 如何在 React 中的单击按钮上使用 fetch API 设置状态 - how to setState with fetch API on click button in React 如何使用反应setState与chrome API - How to use react setState with chrome API 我可以在我的 console.log 中显示 API 数据,但我不能用它来设置状态。 . . 我该如何设置状态? (获取,反应本机) - I could display API data in my console.log, but I can't setState with it . . . how can I setState? (fetch, React Native) 如何通过DataMuse API使用访存和响应组件 - How to use fetch with datamuse API and react components 如何在反应中使用 lifeCyle 和 setState? - How to use lifeCyle and setState in react? 反应。 如何仅使用现有密钥的fetch和setState处理API响应中的缺失密钥? - React. How to deal with missing keys in API response using fetch and setState only for existing keys? React 抛出 TypeError: this is undefined while setState is used with Fetch API - React is throwing TypeError: this is undefined while setState is used with Fetch API 无法使用获取将API数据绑定到React JS中的this.setState - Unable to bind API data to this.setState in React JS using fetch 在React中使用setState的多次提取请求 - Multiple fetch requests with setState in React
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM