【问题标题】:mapping a state property return empty array映射状态属性返回空数组
【发布时间】:2019-12-05 03:27:47
【问题描述】:

我正在编写一个从 xml 文件中获取数据的简单应用程序。 fetchData 函数没问题,并返回一个我存储在我的状态中的数组。

但是当我尝试映射这个数组时,它返回一个空数组。所以我可以记录我的数据,但即使我尝试获取长度属性,它也会返回 0...

你可以在这里看到我的代码:

import React, { Component } from 'react';
import { parseString } from 'xml2js';
import data from './data';

class App extends Component {
  state = {
    parks: []
  };

  componentWillMount() {
    let { parks } = this.state;
    for (let key of data) {
      this.fetchData(parks, key.name, key.url);
    }
    this.setState({ parks });
  }

  fetchData = (parks, name, url) => {
    let free = '';
    let park = {};
    fetch(url)
      .then(response => response.text())
      .then(xml => {
        parseString(xml, function(err, result) {
          if (result) {
            free = result.park.Free[0];
            while (free[0] === '0') {
              free = free.slice(1);
            }
          } else {
            free = 'no info avaible';
          }
        });
        park = {
          name: name,
          free: free
        };
        parks.push(park);
      });
  };

  render() {
    const { parks } = this.state;
    console.log(parks);
    const parkList = parks.map(({ name, free }) => <div>{name}</div>);
    console.log(parkList);
    return <div>{parkList}</div>;
  }
}

export default App;

console.log(parks) 返回如下数组:

[
  {
    "name": "Antigone",
    "free": "245"
  },
  {
    "name": "Arc de Triomphe",
    "free": "91"
  }
]

console.log(parkList) 返回一个空数组

【问题讨论】:

标签: reactjs


【解决方案1】:

问题在于fetch 正在异步运行,fetchData 将在实际获取完成之前返回。所以setStateparks 对象被填充之前被调用,所以render 函数是用空的parks 对象调用的。 console.log 也没有同步运行,因此您会因为对对象的引用而获得不同的输出。

要解决此问题,您必须等待所有提取后才能调用 setState

  componentWillMount() {
    let { parks } = this.state;
    const fetches = []
    for (let key of data) {
      fetches.push(this.fetchData(parks, key.name, key.url));
    }
    Promise.all(fetches)
       .then(()=>this.setState({ parks }));
  }

  fetchData = (parks, name, url) => {
    let free = '';
    let park = {};
    return fetch(url)
      .then(response => response.text())
      .then(xml => {
        parseString(xml, function(err, result) {
          if (result) {
            free = result.park.Free[0];
            while (free[0] === '0') {
              free = free.slice(1);
            }
          } else {
            free = 'no info avaible';
          }
        });
        park = {
          name: name,
          free: free
        };
        parks.push(park);
      });
  };

还值得一看 Javascript 中的async/await。有了这个,您可以编写更易读、更明显的代码。

【讨论】:

  • 非常感谢老兄。我只是尝试使用 async / await 重现相同的结果,但看起来性能更差。你说console.log是异步的,但我觉得很奇怪我可以记录公园(并查看对象的长度属性)但是当我记录parks.length时它返回0。就好像“公园”的值被“ console.log(parks.lenght)" 在 "console.log(parks)" 使用的那个之前。此外,我可以使用我的 react 开发工具查看我的 fetches ......奇怪......这一切让我感到困惑,但我想我理解了这个例子中的 promises 和 async / await 的逻辑
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-05-17
  • 2019-10-31
  • 2020-07-15
  • 2020-04-22
  • 2019-10-22
相关资源
最近更新 更多