Home > Blockchain >  React function running before state change
React function running before state change

Time:12-16

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:

  1. The state update is not immediate
  2. 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

  • Related