I have a function that is run when a user clicks a button, when this function is run it gathers data and updates state. I then have another function which runs that uses some of the data that is added to state, the issue is the state is not updating in time so the function is using old data.
First function
async function callWeather() {
const key = "";
// Get location by user
let location = formData.location;
// Url for current weather
const currentWeatherUrl = `https://api.openweathermap.org/data/2.5/weather?q=${location}&units=metric&appid=${key}`;
// Get the current weather
const currentWeatherResponse = await fetch(currentWeatherUrl);
if (!currentWeatherResponse.ok) {
// Return this message if an error
const message = `An error has occured: ${currentWeatherResponse.status}`;
throw new Error(message);
}
const weatherDataResponse = await currentWeatherResponse.json();
// Update state with data
setWeatherData(weatherDataResponse);
}
Second function
async function callForcast() {
const key = "";
// Get lat & lon from the previous data fetch
const lon = weatherData.coord.lon
const lat = weatherData.coord.lat
// Get forcast data
const forcastWeatherUrl = `https://api.openweathermap.org/data/2.5/forecast?lat=${lat}&lon=${lon}&units=metric&appid=${key}`
const forcastWeatherResponse = await fetch(forcastWeatherUrl);
if (!forcastWeatherResponse.ok) {
const message = `An error has occured: ${forcastWeatherResponse.status}`;
throw new Error(message);
}
const forcastDataResponse = await forcastWeatherResponse.json();
// Update state with the forcast data
setForcastData(forcastDataResponse);
}
This then runs with the onClick calling both functions
function callWeatherAndForcast() {
callForcast();
callWeather();
}
CodePudding user response:
use 'await' before calling callForcast so the second function (callWeather) does'nt get called immediately after calling first function.
async function callWeatherAndForcast() {
await callForcast();
callWeather();
}
also as @tromgy mentioned in the comments, React state updates are not immediate, try calling callWeather function inside a hook which has a dependency on forcastData state
CodePudding user response:
Are you using FunctionComponent or Classes ?
Also, keep in mind that updating the state will trigger a rerendering. This means that:
- The state update is not immediate
- If one of your functions use the data from another, you should take care of these dependencies.
For helping you correctly, I need to know if you use FunctionComponent
or Class
and get the whole Function/Class.
CodePudding user response:
I think you try to call callWeather(); under callForcast after setForcastData state set, and if update state value not affected in call weather you can try to add wait in setForcastData.
Or also try to add wait before callForcast in callWeatherAndForcast onClick
CodePudding user response:
State does not update immediately! Meaning that the function I want to get the new state will get the previous state. To fix this I added callForcast function into a useEffect hook which has a dependency on callWeather because callForcast needs callWeather to update state first. This means when this function is run state will be updated in time.
useEffect (() => {
async function callForcast() {
const key = "";
// Get lat & lon from the previous data fetch
const lon = weatherData.coord.lon
const lat = weatherData.coord.lat
// Get forcast data
const forcastWeatherUrl = `https://api.openweathermap.org/data/2.5/forecast?lat=${lat}&lon=${lon}&units=metric&appid=${key}`
const forcastWeatherResponse = await fetch(forcastWeatherUrl);
if (!forcastWeatherResponse.ok) {
const message = `An error has occured: ${forcastWeatherResponse.status}`;
throw new Error(message);
}
const forcastDataResponse = await forcastWeatherResponse.json();
// Update state with the forcast data
setForcastData(forcastDataResponse);
}
// Call the callForcast function to run
callForcast();
},
// This effect hook is dependent on callWeather
[callWeather])
Now my onClick will only need to call callWeather() function.
Thanks to: @Mohammad Arasteh @Thomas Geenen @tromgy