【问题标题】:Using JS native fetch() api in React ComponentDidMount() results in a pending Promise在 React ComponentDidMount() 中使用 JS 本机 fetch() api 会导致未决的 Promise
【发布时间】:2020-12-10 14:48:36
【问题描述】:

我试图从 componentDidMount() 生命周期方法的公共文件夹中将数据加载到我的项目中。但是,我没有得到想要的 FeatureCollection 对象,而是一个待处理的 Promise

componentDidMount = () => {

    ...

    const data = fetch(`vcd/${this.state.monthFile}`)
        .then(response => response.text())
        .then(async data => {
            return csv2geojson.csv2geojson(data, {
                latfield: 'lat',
                lonfield: 'lng',
                delimiter: ','
            }, (err, data) => {
                if (err) console.log(err);
                console.log(data); // correctly outputs a FeatureCollection, length 30277
                return data;
                // this.setState({ someAttribute: data }) => Also doesn't work.
            })
        })
        .then(data => data); // If to use another Promise chaining, the result would be undefined.

    console.log(data); // a pending Promise

}

我的文件包含 30277 行 * 3 列,大小约为 500Kb,我认为这不应该是数据加载的问题,在咨询了 csv2geojson 和 fetch API 之后,我仍然想不出一个解决方案问题。我很感激任何有用的意见。

编辑:同时使用 async-await 模式并链接另一个 .then 将导致 undefined

【问题讨论】:

  • 为什么this.setState({ someAttribute: data }) 在承诺链中不起作用?

标签: reactjs fetch


【解决方案1】:

fetch 返回一个承诺,这就是你保存到data 的内容。如果你想记录“数据”,那么你有几个选择。

  1. 记录它IN承诺链(你已经这样做了)
  2. 转换为 async/await 并等待获取解析/拒绝

代码

componentDidMount = async () => {

    ...

    const data = await fetch(`vcd/${this.state.monthFile}`)
        .then(response => response.text())
        .then(data => {
            return csv2geojson.csv2geojson(data, {
                latfield: 'lat',
                lonfield: 'lng',
                delimiter: ','
            }, (err, data) => {
                if (err) console.log(err);
                console.log(data);
                return data;
            })
        });

    console.log(data); // a resolved/rejected Promise result
}

【讨论】:

  • 感谢您的意见!我已经尝试了上面的方法,但data 导致undefined。我也尝试链接另一个 .then(),并产生相同的结果,即undefined.
  • @Z.Richard 我不确定您可能会采取什么不同的做法,但出于我自己的理智,我在代码盒中测试了这两种解决方案,这很有效。更新了答案以包含沙盒演示的链接。
【解决方案2】:

JS Fetch 返回一个承诺,因为你正在返回那个承诺。 因此,只需像这样更改您的代码就可以了;

import React, { useEffect, useState } from "react";

export default function ExampleHooks() {
  const [data, setData] = useState(null);
  var csv2geojson = require("csv2geojson");

  useEffect(() => {
    fetch("https://gw3xz.csb.app/sample.csv")
      .then((response) => response.text())
      .then(async (data) => {
        csv2geojson.csv2geojson(
          data,
          {
            latfield: "lat",
            lonfield: "lng",
            delimiter: ","
          },
          (err, data) => {
            if (err) console.log(err);
            setData(data);
          }
        );
      });
  }, []);

  return <div onClick={() => console.log(data)}>show data</div>;
}

或作为类组件:

import React from "react";
var csv2geojson = require("csv2geojson");

class ExampleClass extends React.Component {
  state = {
    data: null
  };

  componentDidMount() {
    fetch(`vcd/${this.state.monthFile}`)
      .then((response) => response.text())
      .then(async (data) => {
        csv2geojson.csv2geojson(
          data,
          {
            latfield: "lat",
            lonfield: "lng",
            delimiter: ","
          },
          (err, data) => {
            if (err) console.log(err);
            this.setState({ data: data });
          }
        );
      });
  }

  render() {
    return <div onClick={() => console.log(this.state.data)}>show data</div>;
  }
}

export default ExampleClass;

工作示例over here

【讨论】:

    猜你喜欢
    • 2017-10-22
    • 2021-05-08
    • 1970-01-01
    • 2017-04-19
    • 2018-12-27
    • 2018-12-19
    • 2016-12-09
    • 1970-01-01
    • 2019-01-05
    相关资源
    最近更新 更多