如何在 React 中处理 fetch API AJAX 响应

Posted

技术标签:

【中文标题】如何在 React 中处理 fetch API AJAX 响应【英文标题】:How to handle fetch API AJAX response in React 【发布时间】: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;

【问题讨论】:

【参考方案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

【讨论】:

以上是关于如何在 React 中处理 fetch API AJAX 响应的主要内容,如果未能解决你的问题,请参考以下文章

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

如何在带有 Jest 的 react-native 中使用模拟的 fetch() 对 API 调用进行单元测试

在 React JS 中使用 fetch 处理响应状态

如何使用 fetch 制作通用 API 调用函数

React.js:使用 Fetch API 和对象数组中的道具加载 JSON 数据

如何使用 React.js 中的 Fetch API 将数据发布到数据库