【问题标题】:How to handle fetch API AJAX response in React如何在 React 中处理 fetch API AJAX 响应
【发布时间】:2017-02-09 11:07:51
【问题描述】:

我正在使用 React 中的 fetch API 发出一个简单的 AJAX 请求,特别是在 componentDidMount() 函数中。

它正在工作,因为控制台似乎正在记录结果。但是,我不知道如何访问响应...

componentDidMount = () => {

      let URL = 'https://jsonplaceholder.typicode.com/users'

         fetch(URL)
         .then(function(response) {
            let myData = response.json()
            return myData;
         })
         .then(function(json) {
            console.log('parsed json', json)
         })
         .catch(function(ex) {
            console.log('parsing failed', ex)
         })

   } // end componentDidMount

我尝试在 fetch 方法之外访问 myData,但这会引发错误,指出它未定义。所以只能在函数范围内访问。

然后我尝试了这个:

     .then(function(response) {
        let myData = response.json()
        // return myData;
        this.setState({
           data: myData
        })
     })

这一次,我得到Cannot read property 'setState' of undefined(…)

如何将获取响应传递给状态,甚至只是一个全局变量?


更新

import React, { Component } from 'react';
import './App.css';

class App extends Component {

   constructor(props) {
      super(props);
      this.state = {
         data: null
      }
   }

   componentDidMount() {
      let URL = 'https://jsonplaceholder.typicode.com/users'  
         fetch(URL)
         .then( (response) => {
            let myData = response.json()
            // return myData;
            this.setState({
               data: myData
            })
         })
         .then( (json) => {
            console.log('parsed json', json)
         })
         .catch( (ex) => {
            console.log('parsing failed', ex)
         })
         console.log(this.state.data)
   } // end componentDidMount

  render() {
    return (
      <div className="App">
         {this.state.data}
      </div>
    );
  }
}

export default App;

【问题讨论】:

    标签: javascript json reactjs response fetch-api


    【解决方案1】:

    您在this.setState 的正确轨道上,但是当您在处理响应的函数中调用它时,this 不再位于组件的上下文中。使用=&gt; 函数维护this 的上下文。

    fetch(URL)
        .then((res) => res.json())
        .then((json) => this.setState({data: json}));
    

    【讨论】:

    • 谢谢。这是有道理的,但我仍然没有得到想要的结果。请看我的更新...
    • 您仍然在响应处理程序的上下文中引用this,而不是在组件的上下文中。您要么需要将组件绑定到您的函数,要么使用胖箭头函数来维护 this 的上下文。
    • 我现在看到你的更新了。您现在已经用箭头函数声明了componentDidMount。这实质上会破坏您的组件,因为现在该箭头函数内的this 不再位于组件的上下文中。你应该像以前一样声明它componentDidMount() {}。获取响应中的响应处理程序是需要使用箭头函数的处理程序。
    • 仍然无法正常工作:/ 更改了我的更新...myData 仍然持有我在状态初始化中声明的null 值...
    • 您是否尝试过在您的render() 方法中渲染this.state.data?一旦你调用this.setState({data: myData}),它将触发你的组件的渲染。此外,如果您使用的是 Chrome,您可以使用 React Devtools Chrome 扩展程序进行调试。它将允许您在调用 this.setState({data: myData}) 后查看组件的状态。
    【解决方案2】:

    setState 未定义,因为您使用经典函数语法而不是箭头函数。箭头函数从 'parent' 函数中获取 'this' 关键字,经典的 fu​​nction() {} 创建它自己的 'this' 关键字。 试试这个

    .then(response => {
        let myData = response.json()
        // return myData;
        this.setState({
           data: myData
        })
     })
    

    【讨论】:

      【解决方案3】:

      据我所知,你有两个问题,response.json() 返回一个承诺,所以你不想将myData 设置为承诺,而是首先解决承诺,然后你可以访问你的数据。

      其次,this 在您的 fetch 请求中不在同一个范围内,这就是您未定义的原因,您可以尝试将 this 的范围保存在 fetch 之外:

      var component = this;
      
      fetch(URL)
       .then( (response) => {
          return response.json()    
       })
       .then( (json) => {
          component.setState({
             data: json
          })
          console.log('parsed json', json)
       })
       .catch( (ex) => {
          console.log('parsing failed', ex)
       })
       console.log(this.state.data)
      

      【讨论】:

      • 谢谢老兄!我为此浪费了 3 个小时
      【解决方案4】:

      你需要将当前上下文绑定到目标函数

      fetch(URL)
               .then(function(response) {
                  return response.json();
               })
               .then(function(json) {
                  this.setState({data: json})
               }.bind(this))
               .catch(function(ex) {
                  console.log('parsing failed', ex)
               })
      

      【讨论】:

        【解决方案5】:

        反应原生

        import React, { Component } from 'react';
        
        import {
        AppRegistry,
        StyleSheet,
        Text,
        View,
        } from 'react-native';
        
        export default class SampleApp extends Component {
        constructor(props) {
        super(props);
        this.state = {
            data:  'Request '
            }
        }
        
        componentDidMount = () => {
        fetch('http://localhost/replymsg.json', {
                              mode: "no-cors",
                              method: "GET",
                              headers: {
                                "Accept": "application/json"
                              },} )
                              .then(response => {
                              if (response.ok) {
        
                                  response.json().then(json => {
        
                                    console.warn( JSON.stringify(json.msg ));
                                      this.setState({
                                         data: JSON.stringify(json)
                                    })
        
                                });
                              }
                            }); 
        
        }
        
        
        
        render() { 
        return (
            <Text>  {this.state.data}</Text>
            );
            }
        }
        
        AppRegistry.registerComponent('SampleApp', () => SampleApp);
        

        JSON 文件 创建一个文件 replymsg.json 并放在下面的内容,它应该托管到本地主机,如:http://localhost/replymsg.json

        {"status":"200ok","CurrentID":28,"msg":"msg successfully reply"}
        

        【讨论】:

          【解决方案6】:

          通过使用“=>”而不是函数来更改访问响应数据的方式,使其处于相同的上下文中。

          componentDidMount = () => {
          
                let URL = 'https://jsonplaceholder.typicode.com/users'
          
                   fetch(URL)
                   .then(function(response) {
                      let myData = response.json()
                      return myData;
                   })
                   .then((json) => {
                      console.log('parsed json', json)
                   })
                   .catch(function(ex) {
                      console.log('parsing failed', ex)
                   })
          
          } // end componentDidMount
          

          【讨论】:

            猜你喜欢
            • 2017-01-16
            • 2017-03-07
            • 1970-01-01
            • 2016-07-13
            • 1970-01-01
            • 2018-09-18
            • 1970-01-01
            • 2017-03-10
            • 1970-01-01
            相关资源
            最近更新 更多