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