通过数组和 API 调用进行异步映射时如何在 React 中设置状态

How to setState in React when async mapping through array and API call

我正在尝试在 React 中通过我的收藏夹中的 map() 来从状态中的每个条目中获取数据。数据应该存储在另一个状态stocks中,并以table.

显示

Map() 通过状态和获取数据有效,我可以在控制台日志中看到日期。但不会存入state。

如何将数据添加到状态?

代码如下:

  // Calling the function on component mount
  useEffect(() => {
      tableFetch();
  }, []);

  const [favorites, setFavorites] = useState(["aapl", "arlv"]);
  const [stocks, setStocks] = useState([]);

    // fetch symbol data and stores it in stocks
      const tableFetch = () => {
        favorites.map( async (favorites) => {
          const data = await fetch(
                `https://cloud.iexapis.com/stable/stock/${favorites}/quote?token=${token}`
              );
          const stocksData = await data.json();
          console.log(stocksData)
          setStocks(stocksData);
        });
      }

这里有一些问题。

  1. 当您在获得响应后进行 API 调用时,状态将被新数据覆盖或可能会发布范围可用性

建议: 2. 为什么不进行多次 API 调用,当它们结算时,收集所有信息然后设置状态。

useEffect(() => {
    tableFetch();
  }, []);

  const tableFetch = async () => {
    // Note: the below code will create urls & make parallel calls
    let axiosFetch = favorites.reduce((axiosCalls, url) => {
      axiosCalls.push(axios.get(`https://reqres.in/api/users?page=${url}`));
      return axiosCalls;
    }, []);

    // Here promises will settle and will collect all the data.
    await axios
      .all(axiosFetch)
      .then((data) => {
        let dataCollected = data.reduce((dataCollected, response) => {
          dataCollected = dataCollected.concat(response.data.data);
          return dataCollected;
        }, []);
        // After collecting all the data we can set data into state at once.
        setStocks(dataCollected);
      })
      .catch((error) => {
        console.log("collect errors", error);
      });
  };

Sample Code Example, you can play around

Note: I was using Axios library, the same thing can be done using fetch too.

我已经使用 fetch 完成了这些更改,希望对您有所帮助。

 const tableFetch = async () => {
    // Note: the below code will create urls & make parallel calls
    let urls = favorites.reduce((axiosCalls, url) => {
      axiosCalls.push(`https://reqres.in/api/users?page=${url}`);
      return axiosCalls;
    }, []);

    const texts = await Promise.all(
      urls.map(async (url) => {
        const resp = await fetch(url);
        return resp.json();
      })
    );

    let dataCollected = texts.reduce((dataCollected, response) => {
      dataCollected = dataCollected.concat(response.data);
      return dataCollected;
    }, []);
    // After collecting all the data we can set data into state at once.
    setStocks(dataCollected);
  };

POC Link using fetch method