【问题标题】:Fetch data with React使用 React 获取数据
【发布时间】:2016-08-08 18:31:47
【问题描述】:

我对 React 很陌生,我正在尝试使用 fetch api 从服务器调用数据。

如果我想创建一个帮助类来获取这样的数据

import { Promise } from 'es6-promise';
import fetch from 'isomorphic-fetch';
let responseData = response => {
  return response;
};

let getData = (dataURL, headers) => {
  let result = {
    data: [],
    message: ''
  };
  if (dataURL === null || dataURL === undefined || dataURL === '') {
    result.message = 'URL is not correct';
    responseData(result);
  }
  fetch(dataURL, headers)
    .then(response =>{
      if (response.ok) {
        response.json().then(data => {
          result.data = data;
          result.message = response.statusText;
          responseData(result);
        });
      }else{
        result.message = 'Network response was not ok.';
        responseData(result);
      }
    })
    .catch(err => console.log(err));
};

exports.responseData = responseData;
exports.getData = getData;

当数据可用时,我会要求 React 渲染视图,在等待期间,它会显示一个加载图标。

我将调用放在componentDidMout 中,但在执行时,结果始终是undefined

componentDidMount() {
    var self = this;
    let result = util.getData('http://localhost:3001/menus');
    const { dispatch } = this.props;
    // dispatch(menuActions.fetchMenusIfNeeded());
    if (result !== null && result !== undefined) {
      if (this.isMounted()) {
        this.setState({
          items: result.data.results
        });
      }
    }
  }

在 Angular 中,只要数据可用,它就会相应地更新,但我真的不明白如何在 React 中做到这一点。

编辑 1: 更新助手类:

import { Promise } from 'es6-promise';
import fetch from 'isomorphic-fetch';


let getData = (dataURL, headers) => {
  return fetch(dataURL, headers);
};

exports.getData = getData;

它总是会返回一个Promise,所以我可以链接其他组件中的数据处理程序。我需要通过读取组件中的Response 对象来处理消息返回的唯一问题。

在 React 组件中:

componentWillMount() {
    util.getData('http://localhost:3001/menus')
      .then(response =>{
        if (response.ok) {
          response.json().then(data => {
            console.log(data);
            this.setState({
              items: data.result
            });
          });
        }
      })
      .catch(err => console.log(err));
  }

但是每当它接收到数据时,render() 函数已经完成,我应该强制它再次更新吗?

【问题讨论】:

  • 你不会从getData 函数返回任何东西,但即使你确实返回了result,这是异步的,所以你不会在componentDidMount 中看到result
  • 我理解了这个问题,但是每当我返回 Promise 时,我应该如何通知 React 更新 render() 函数。
  • 一篇文章回答了关于如何、何时以及在哪里获取 React 数据的所有问题:How to fetch data in React。也许它有助于人们在偶然发现这个问题时了解它。

标签: javascript reactjs fetch


【解决方案1】:

result 不是数据,它是一个 Promise,可以用来访问数据。您需要从 fetch 返回 Promise,还需要从 then 中的 getData 返回数据,并更新您的 React 代码。

获取数据变化

 return fetch(dataURL, headers)
  .then(response =>{
     if (response.ok) {
       response.json().then(data => {
         result.data = data;
         result.message = response.statusText;
         return responseData(result);
       });
     } else {
       result.message = 'Network response was not ok.';
       return responseData(result);
     }
  })
  .catch(err => console.log(err));

应对变化

componentDidMount() {
   var self = this;
   let result = util.getData('http://localhost:3001/menus');
   const { dispatch } = this.props;
   // dispatch(menuActions.fetchMenusIfNeeded());
   result.then((data) => {
      if (this.isMounted()) {
        this.setState({
          items: data.results
        });
      }
   });
 }

【讨论】:

  • 感谢您的回答,我尝试将then() 用于result,但result 始终为undefined,我是否应该尝试直接从fetch 返回结果?跨度>
  • 你能看看我编辑的函数调用吗?我应该如何让 React 知道数据并更新 render()
  • 两个想法,确定你这个条件是真的吗?:if (response.ok) {,无论哪种方式,我认为问题可能是你正在初始化你的状态:data: [] 但你正在设置结果进入状态items:。你可能需要更新到:this.setState({ data: data.results }),假设你的渲染函数在data而不是items上运行
  • 当我把console.log放进去的时候,我总是看到数据已经被记录了所以我认为if(reponse.ok)是真实的,我没有先初始化数据,我只是设置了items通过该功能,这是正确的做法还是我应该先尝试初始化this.props.items = []
【解决方案2】:

在收到响应之前,您不应尝试延迟组件的渲染和/或安装。相反,您应该使用回调来确保在请求结束后一切都按照您的意愿进行更新。

您只需修改getData 的代码,使其在请求结束后执行回调。您有两种选择。

  1. 使getData 函数接受第三个参数callback 并在处理响应后调用此方法。这大致如下所示:

let getData = (dataURL, headers, callback) => {
  let result = {
    data: [],
    message: ''
  };
  if (dataURL === null || dataURL === undefined || dataURL === '') {
    result.message = 'URL is not correct';
    responseData(result);
  }
  fetch(dataURL, headers)
    .then(response =>{
      if (response.ok) {
        response.json().then(data => {
          result.data = data;
          result.message = response.statusText;
          responseData(result);
        });
      }else{
        result.message = 'Network response was not ok.';
        responseData(result);
      }
      callback(result);
    })
    .catch(err => console.log(err));
};

请记住,这不是实际实现的样子。如果发生异常,回调将不会被调用,并且调用代码永远不会知道发生了什么。但从本质上讲,这就是它的工作方式。

  1. 使getData 函数返回由fetch API 创建的Promise。这是我个人会使用的,因为它看起来更干净,并且我会在一周中的任何一天接受 Promises 而不是回调。

let getData = (dataURL, headers) => {
  let result = {
    data: [],
    message: ''
  };
  if (dataURL === null || dataURL === undefined || dataURL === '') {
    result.message = 'URL is not correct';
    responseData(result);
  }
  return fetch(dataURL, headers)
    .then(response =>{
      if (response.ok) {
        response.json().then(data => {
          result.data = data;
          result.message = response.statusText;
          responseData(result);
        });
      }else{
        result.message = 'Network response was not ok.';
        responseData(result);
      }
      return result;
    })
    .catch(err => console.log(err));
};

只需添加 return 关键字即可返回 Promise,然后您就可以将处理程序链接到您的心愿。

好的,我们如何使用它?这实际上非常简单。您现在可以告诉getData 方法在收到响应(或引发异常)后执行某些操作。

例如,您可以在 React 组件的 componentWillMount 方法中执行此操作。

componentWillMount() {
    getData('http://example.com', new Headers())
        .then(function(result) {
            this.setState({ items: result });
        });
}

您还可以通过在请求之前设置一个标志并在请求之后重置它来控制加载面板(当然还有回调)。

【讨论】:

  • 如果我不直接返回获取,我总是会收到一个空白对象或undefined,在这种情况下有没有办法让Promise返回?
  • 我认为 react 组件中的“this”在回调期间不会再出现在范围内
猜你喜欢
  • 2022-01-04
  • 1970-01-01
  • 2021-08-16
  • 2020-08-21
  • 2021-05-05
  • 2019-05-08
  • 1970-01-01
  • 2019-01-01
  • 2022-01-25
相关资源
最近更新 更多