繁体   English   中英

在 useEffect 中只运行一次函数

[英]Run a function inside useEffect only once

所以我有一个 useEffect 挂钩,它有一个名为 callForcast() 的函数,它依赖于 callWeather,所以当 callWeather() 函数运行时,callForcast() 运行。 使用 onClick 和 callForcast() 调用 callweather() 我在 useEffect() 中添加了一个调用,但这会导致无限循环。

我怎样才能让这个功能运行一次。

 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); } // Causing infinite loop callForcast(), }, [callWeather])

这就是 callForcast 函数所依赖的

 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). } // Get data if no error const weatherDataResponse = await currentWeatherResponse;json(); // Update state with data setWeatherData(weatherDataResponse); }

为什么这依赖于callWeather 它不使用callWeather

它一遍又一遍地执行,大概是因为无论callWeather是什么,它都会在每次渲染时发生变化。 (可能在每次渲染时重新声明和/或重新分配。)

如果这个效果应该只执行一次,使用一个空的依赖数组:

useEffect(() => {
  // the code in the effect
}, []);

这将在组件首次加载时仅执行一次效果。


或者...

当 callWeather() 函数运行时,callForcast() 运行

如果您想在调用callForcast()时调用callWeather() ,那么useEffect是错误的工具。 只要定义好你要调用的函数,想调用的时候就调用。 例如:

const callForcast = () => {
  // the code in the function
};

const callWeather = () => {
  // the code in the function
  
  callForcast();
};

另一种可能...

如果您一个作为依赖项的状态值,并且希望在依赖项更改时随时调用效果,请使用该状态值作为依赖项:

useEffect(() => {
  // the code in the effect
}, [weatherData]);

要么...

如果此功能只需要从另一个操作提供给它的一些数据,请提供该数据。 例如:

const callForcast = (dataNeeded) => {
  // the code in the function
};

const callWeather = () => {
  // the code in the function
  
  callForcast(someData);
};

总的来说,在什么情况下你想执行callForcast并不完全清楚。 (虽然你可能在我输入这个问题时澄清了这一点。)但在你的原始代码中,它在每个渲染器上执行的原因是因为callWeather在每个渲染器上都在变化并且肯定是错误的依赖使用。

尝试在您的效果中实际调用callWeather 如果它是异步的,你可以在 callForcast 中调用它

useEffect (() => {
    // callWeather();

    async function callForcast() {
      await callWeather();

      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);
    }
    // Causing infinite loop
    callForcast(); 

  }, [callWeather])

此外,您应该让callWeather在承诺中返回您的数据,以便您可以在callForcast fn 中提取它。 const data = await callWeather();

编辑:看到你可能只是想要的更新

  // will run callForcast every time 
  useEffect (() => {
    async function callForcast() {
       ...
    }
    callForcast(); 
  }, [weatherData]);

要么

  async function callWeather() {
    ...
    setWeatherData(weatherDataResponse);
    return weatherDataResponse;
  }

  useEffect (() => {
    async function callForcast() {
       const weatherData = await callWeather();
       ...
    }
    callForcast(); 
  }, [callWeather]);

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM