pedrofromperu
pedrofromperu

Reputation: 105

ReactJS : Failing to fetch an API

Hey I'm trying to fetch an API, but it dosnt returns anything.

I've checked and I cannot access my pre-built values inside my fetch.

How can I access my values inside the fetch ?

import React, { useState, useEffect } from 'react';

function App() {
  const [ positionLat, setPositionLat ] = useState('') ;
  const [ positionLong, setPositionLong] = useState('') ;
  
  navigator.geolocation.getCurrentPosition(function(position) {
    setPositionLat(position.coords.latitude);
    setPositionLong(position.coords.longitude);
  });

console.log(positionLat) // returns good result
console.log(positionLong) // returns good result

// I obviously need to call those values inside my fetch

useEffect(() => {
  console.log(positionLat) // returns undefined
  console.log(positionLong) // returns undefined
  fetch(`https://api.openweathermap.org/data/2.5/weather?lat=${positionLat}&lon=${positionLong}&appid={api_key}b&units=metric`)
   .then(res => {
    return res.json();
   })
   .then(data => {
    console.log(data)
   })
}, []);

  return (
    <div className="App">
      <p>lattitude :{positionLat}</p>
      <p>longitude :{positionLong}</p>
    </div>
  );
}

export default App;

Upvotes: 2

Views: 59

Answers (1)

CertainPerformance
CertainPerformance

Reputation: 370639

One option is to change your effect hook to only run the main body once the values are defined:

useEffect(() => {
  if (positionLat === '' || positionLong === '') {
    return;
  }
  // rest of function
  fetch(...
}, [positionLat, positionLong]);

You also need to fix your geolocation call to occur only once, on mount.

useEffect(() => {
  navigator.geolocation.getCurrentPosition(function(position) {
    setPositionLat(position.coords.latitude);
    setPositionLong(position.coords.longitude);
  });
}, []);

Another option is to split it up into two components, and only render the child component (which does the fetching) once the geolocation call is finished, which might look cleaner.

const App = () => {
    const [coords, setCoords] = useState();
    useEffect(() => {
        navigator.geolocation.getCurrentPosition(function (position) {
            setCoords(position.coords);
        });
    }, []);
    return coords && <Child {...coords} />;
};
const Child = ({ latitude, longitude }) => {
    useEffect(() => {
        fetch(`https://api.openweathermap.org/data/2.5/weather?lat=${latitude}&lon=${longitude}&appid={api_key}b&units=metric`)
            .then(res => res.json())
            .then(data => {
                // do stuff with data
            })
            // .catch(handleErrors); // don't forget to catch errors
    }, []);
    return (
        <div className="App">
            <p>latitude :{latitude}</p>
            <p>longitude :{longitude}</p>
        </div>
    );
};

Upvotes: 4

Related Questions