[英]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])
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.