簡體   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