Home > OS >  Using multiple axios get requests inside useEffect yields undefined values
Using multiple axios get requests inside useEffect yields undefined values

Time:11-10

I'm very new to React and web development as a whole, and I know the code is styled terribly but bear with me please.

I'm attempting to get weather data with openweathermap API, which I have to use latitude and longitude for my desired location, which I am supposed to get from their separate geocoding API when I feed it the capital and country code of a country I'm interested in.

I'm kind of unsure how to "stack" these requests so that the first coordinate request goes through and gives the coordinates to the second, weather request. My problem, is that the coordinates (which I otherwise get successfully) are given as undefined to my next request, and I can't figure out why, and I've tried a lot.

const Content = ({result}) => {
  const languages = [result['languages']]
  const [weather, setWeather] = useState([])
  const [coordinate, setCoordinates] = useState([])
  const api_key = process.env.REACT_APP_API_KEY

  useEffect(() => {
    axios
        .get(`http://api.openweathermap.org/geo/1.0/direct?q=${result['capital']},${result['cca2']}&limit=1&appid=${api_key}`)
        .then(response => {
          setCoordinates(response.data)
        })
        .then(() =>
            axios
                .get(`https://api.openweathermap.org/data/3.0/onecall?lat=${coordinate['lat']}&lon=${coordinate['lon']}&exclude=1&appid=${api_key}`)
                .then(response => {
                  setWeather(response.data)
            }))
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [])

CodePudding user response:

setCoordinates does not update coordinate immediately, as React batches state updates. States are therefore updated asynchronously.

If your second request is dependent on state changes to the coordinate array, then you should move it into its own useEffect hook:

const Content = ({result}) => {
  const languages = [result['languages']]
  const [weather, setWeather] = useState([])
  const [coordinate, setCoordinates] = useState([])
  const api_key = process.env.REACT_APP_API_KEY

  useEffect(() => {
    axios
        .get(`http://api.openweathermap.org/geo/1.0/direct?q=${result['capital']},${result['cca2']}&limit=1&appid=${api_key}`)
        .then(response => {
            setCoordinates(response.data)
        });
  }, []);

  // Your second API call is dependent on state changes to `coordinate`
  useEffect(() => {
    axios
        .get(`https://api.openweathermap.org/data/3.0/onecall?lat=${coordinate['lat']}&lon=${coordinate['lon']}&exclude=1&appid=${api_key}`)
        .then(response => {
            setWeather(response.data)
        });
  }, [coordinate]);
};

CodePudding user response:

const Content = ({result}) => {
  const languages = [result['languages']]
  const [weather, setWeather] = useState([])
  const [coordinate, setCoordinates] = useState([])
  const api_key = process.env.REACT_APP_API_KEY

  useEffect(() => {
    let coordinateResult = [];
    axios
        .get(`http://api.openweathermap.org/geo/1.0/direct?q=${result['capital']},${result['cca2']}&limit=1&appid=${api_key}`)
        .then(response => {
          coordinateResult = response.data;
        })
        .then(() =>
            axios
                .get(`https://api.openweathermap.org/data/3.0/onecall?lat=${coordinateResult['lat']}&lon=${coordinateResult['lon']}&exclude=1&appid=${api_key}`)
                .then(response => {
                  setCoordinates(coordinateResult);
                  setWeather(response.data)
            }))
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [])

Focus that setState function is asynchronous.

  • Related