【问题标题】:Why is my component not receiving asynchronous data?为什么我的组件没有接收到异步数据?
【发布时间】:2021-12-31 10:49:58
【问题描述】:

我正在学习 React,并且一直遵循教程,直到创建一些组件、传递道具、设置状态和使用 useEffect() 查询 API,此时我想尝试用我所知道的东西来构建一些东西到目前为止。

这是我的 App 组件:

import './App.css';
import CoinList from './components/CoinList/CoinList';
import { useState, useEffect } from 'react';

        
const heldCoins = ['bitcoin', 'ethereum', 'terra-luna']
    const [coins, setCoins] = useState(null)

    async function getCoinData(coinArray) {
        let myCoins = []  // think should use map to create this array
        for await (let coin of coinArray) {
            fetch(`https://api.coingecko.com/api/v3/coins/${coin}`)
                .then(res => res.json())
                .then(data => {
                    const coinData = {
                        coinName: data.id,
                        price: data.market_data.current_price.gbp
                    }
                    myCoins.push(coinData)
                })
        }
        return myCoins
    }

    useEffect(() => {
        getCoinData(heldCoins).then(data => setCoins(data))
    }, [])

    return (
        <>
            {coins && <CoinList type="holding" coins={coins} />}
        </>
    )
}
export default App;

我意识到它在使用 async 和 .then() 时有点混乱,我可能应该使用 map 来创建新数组,但我觉得这应该可以工作......

getCoinData 是一个返回数据对象数组的承诺。一旦返回,它用于在 useEffect 挂钩中使用 setCoins 更新状态。我希望这会触发重新渲染,并且数据可用于 CoinList 组件。

但是,空数组在 api 数据返回之前被传递给 CoinList。

相同的过程在代码中运行,我无法确定我哪里出错了。

【问题讨论】:

  • 尝试在钩子的依赖数组中添加getCoinData和holdCoins。

标签: javascript reactjs asynchronous react-hooks


【解决方案1】:

我对您的 getCoinData 函数中的内容持怀疑态度。

    async function getCoinData(coinArray) {
        let myCoins = [];
        for await (let coin of coinArray) { // here coinArray is not an async iterable, so there's almost no wait happening here
            fetch(/*some api/)
                .then(/*some code*/)
                .then(data => {
                    // some code
                    myCoins.push(coinData)
                })
        }
        return myCoins // I don't see how this waits for the fetch to finish
    }

如果您阅读了我在上面的代码 sn-p 中添加的 cmets,您会看到您的退货发生在 fetch 完成之前,这就是为什么如果我没记错的话您会得到一个空的退货。

理想情况下,您可以使用Promise.all 而不是有点乱的for-await-of,就像这样,

async function getCoinData(coinArray) {
  const promisesArray = coinArray.map((coin) =>
    fetch(`https://api.coingecko.com/api/v3/coins/${coin}`)
      .then((res) => res.json())
      .then((data) => {
        const coinData = {
          coinName: data.id,
          price: data.market_data.current_price.gbp,
        };
        return coinData;
      });
  );
  await Promise.all(promisesArray);
  return coinData;
}

这样做,您实际上是在等待每个fetch 完成执行,而不是直接返回。

【讨论】:

    【解决方案2】:

    使用 promise all,启动并行请求

    async function getCoinData(coinArray) {
      const prms = coinArray.map((coin) =>
        fetch(`https://api.coingecko.com/api/v3/coins/${coin}`)
          .then((res) => res.json())
          .then((data) => {
            const coinData = {
              coinName: data.id,
              price: data.market_data.current_price.gbp,
            };
            return coinData;
          })
      );
      return Promise.all(prms);
    }
    

    【讨论】:

      猜你喜欢
      • 2020-12-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-02-09
      • 2020-05-10
      • 1970-01-01
      相关资源
      最近更新 更多