反应使用状态数组不更新

时间:2020-06-29 15:45:53

标签: javascript reactjs axios

我正在尝试为获取天气数据调用API,我需要将每个返回的数据添加到数组状态。但是它不起作用,并且仅显示最后添加的数据。有人可以解释一下为什么会发生这种情况并给我解决办法

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


const data = require('../src/data/Step1'); //Importing json file
const axios = require("axios");
function App() {

    //React Hook to save weather data
    const [weatherData, setWeatherData] = useState([]);

    //UseEffect to call getData function
    useEffect(() => {

        //call getData for each sending city code one by one
        data.List.map(city => getData(city.CityCode));

    }, []);

    //getData function
    async function getData(cityCode) {
        //Axios get request to http get request
        const response = await axios.get('http://api.openweathermap.org/data/2.5/group?id=' + cityCode + '&units=metric&appid=24e343673cb58392072a12e4705b1260');

        //adding each weather object to weather data Array
        setWeatherData([...weatherData,response.data.list[0]]);

    }
    if (weatherData.length > 1) {
        return (
            <div>
                {
                    <div className="container mt-5">
                        {weatherData.map(x => (
                            <div className="row mt-2 ">
                                Id : {x.data.id} {" | "}
                                Name :{x.data.name} {" | "}
                                Description : {x.data.weather[0].description} {" | "}
                                Temperature : {x.data.main.temp}
                            </div>
                        ))}

                    </div>
                }
            </div>
        );
    } else {
        return (
            <div>
                <h1>Loading</h1>
            </div>
        )
    }
}

export default App;

2 个答案:

答案 0 :(得分:1)

setState不会同步发生,因此不能保证下次调用该状态时会更新该状态。而是尝试以下

   async function getData(cityCode) {

        const response = await axios.get('http://api.openweathermap.org/data/2.5/group?id=' + cityCode + '&units=metric&appid=24e343673cb58392072a12e4705b1260');

        //adding each weather object to weather data Array
        setWeatherData(function (currentWeatherData) {
            return [...currentWeatherData, response.data.list[0]];
          });

    }

这是一个副本示例link

答案 1 :(得分:0)

实际上,回调weatherData是stale closure。也许以下方法会起作用:

//using useCallback so the dependency of getData to the
// effect won't cause the effect to run other than when
// the component mounts
const getData = React.useCallback(async function getData(
  cityCode
) {
  const response = await axios.get(
    'http://api.openweathermap.org/data/2.5/group?id=' +
      cityCode +
      '&units=metric&appid=24e343673cb58392072a12e4705b1260'
  );
  setWeatherData((weatherData) => [
    //using callback so weatherData is not a dependency
    ...weatherData,
    response.data.list[0],
  ]);
},
[]);
useEffect(() => {
  //if you don't use the result of a map then use forEach instead
  data.List.forEach((city) => getData(city.CityCode));
}, [getData]);

您可以将回调传递给状态设置器setWeatherData,以接收当前状态并返回新状态。