Should be getting the values for latitude and longitude but for some reason I am getting the initial state which is "null" and then in the same time getting another response with the data in the console.
As seen in the image, it first returns that it is null and then later (without refreshing or anything) returns the values. BELOW IS MY CODE
This is where I get my value for coords (from a react library)
//Getting geolocation
const {coords, isGeolocationAvailable , isGeolocationEnabled} = useGeolocated({
positionOptions: {
enableHighAccuracy: false
},
userDecisionTimeout: 5000,
})
//Setting Latitude and Longitude states
useEffect (() => {
if (coords) {
setLatitiude(coords.latitude)
setLongitude(coords.longitude)
}
}, [coords]);
//Fetch data from API
useEffect (() => {
console.log(`Latitude = ${latitude} and Longitude = ${longitude}`)
//Function to call API
const weatherForecast = async () => {
await axios.get(`${API_ENDPOINT}lat=${latitude}&lon=${longitude}&exclude=hourly,daily&appid=${API_KEY}`)
.then((res) => {
setWeatherDetails(res.data)
})
}
if(latitude !== null & longitude !== null) {
weatherForecast()
} else {
console.log("Error getting data")
}
}, [latitude , longitude]);
When I first npm start the frontend it works as should but the moment i refresh this is what happens. Any idea what is going on and why this looks like it is re rendering three times to get the result. As a result of that behaviour my API isn't getting the needed data and returning an error.
CodePudding user response:
You're getting null
value for the first time because you're logging it before the coords
data is even loaded.
try this instead
//Getting geolocation
const {coords, isGeolocationAvailable , isGeolocationEnabled} = useGeolocated({
positionOptions: {
enableHighAccuracy: false
},
userDecisionTimeout: 5000,
})
//Setting Latitude and Longitude states
useEffect (() => {
if (coords) {
setLatitiude(coords.latitude)
setLongitude(coords.longitude)
}
}, [coords]);
//Function to call API
const weatherForecast = async () => {
await axios.get(`${API_ENDPOINT}lat=${latitude}&lon=${longitude}&exclude=hourly,daily&appid=${API_KEY}`)
.then((res) => {
setWeatherDetails(res.data)
}).catch(() => {
console.log("Error getting data")
})
}
//Fetch data from API
useEffect (() => {
if(latitude !== null && longitude !== null){
console.log(`Latitude = ${latitude} and Longitude = ${longitude}`)
weatherForecast()
}
}, [latitude , longitude]);
CodePudding user response:
A useEffect is called after the component has rendered. So the first time, latitude and longitude (and probably cords are null).
The second time I would guess cords exists and sets long and lat. Which triggers a re-render since your second useEffect has them in its dependency. array
And after the third render long and lat are set.
In react it is very common to have multiple re-renders.
CodePudding user response:
Just to add to reason out for the two renderings(which actually should be one) before you actually get the values: React StrictMode which by default is enabled, will cause the useEffect to run twice but only in development mode regardless of the dependencies after the INITIAL rendering to ensure that you are aware of all the possible side effects and that the cleanup handlers work as expected. You can find more on it here.