为什么 React 会多次调用我的一些 App 函数?

  • 本文关键字:App 函数 调用 React reactjs
  • 更新时间 :
  • 英文 :


我正在调试一个React应用程序,注意到我的一些函数被多次调用,我无法解释。

我最初认为这是某种";显影剂特征";并尝试运行一个构建,我所能看到的是,不应该调用的API是否被调用了一次而不是两次:

import { useCallback, useState } from "react";
function App() {
const cities = ["montreal", "london", "shanghai"];
const [city, setCity] = useState(cities[0]);
const getCityParameter = useCallback(
(newCity) => {
console.log("[1] getCityParameter");
console.log(`newCity: ${newCity}`);
console.log(`city: ${city}`);
return (newCity ?? city).toUpperCase();
},
// eslint-disable-next-line react-hooks/exhaustive-deps
[city]
);
const [cityParameter, setCityParameter] = useState(getCityParameter());
const handleChange = useCallback(
(event) => {
const newCity = event?.target.value;
console.log("handleCityChange");
console.log(`newCity: ${newCity}`);
if (newCity !== undefined) {
setCity(newCity);
}
const newCityParameter = getCityParameter(newCity);
setCityParameter(newCityParameter);
},
// eslint-disable-next-line react-hooks/exhaustive-deps
[city]
);
return (
<>
<select onChange={handleChange} value={city}>
{cities.map((city) => {
return (
<option value={city} key={city}>
{city}
</option>
);
})}
</select>
<div>{cityParameter}</div>
</>
);
}
export default App;

我在这里创建了这个代码沙盒:https://codesandbox.io/s/restless-butterfly-brh7fk?file=/src/App.js

如果清除控制台日志并更改下拉列表,您会注意到getCityParameter被调用了3次,而我希望它被调用一次。

这似乎是一个相当低级的React功能;不那么小";这是我能想出的最好的再现行为的方法。

有人能解释一下吗?

在更改处理程序中,首先:

const newCityParameter = getCityParameter(newCity);

这就是getCityParameter的一个调用。然后,由于调用了状态设置器,组件将重新呈现。此:

const [cityParameter, setCityParameter] = useState(getCityParameter());

就像做

const result = getCityParameter();
const [cityParameter, setCityParameter] = useState(result);

每次渲染组件时都会再次调用该函数,因此您可以再次看到它。最后,因为您处于严格模式:

root.render(
<StrictMode>
<App />
</StrictMode>
);

该应用程序第二次重新渲染,因此getCityParameter再次运行,在下拉列表更改时总共调用了3次。

当然,初始状态值只在组件安装时使用,这意味着每次在不需要的时候渲染组件时调用函数可能会被视为不必要或令人困惑。如果您希望getCityParameter在重新渲染时不被调用,而只在装载时被调用以确定初始状态值,请使用useState的函数版本。更改

const [cityParameter, setCityParameter] = useState(getCityParameter());

const [cityParameter, setCityParameter] = useState(getCityParameter);

最新更新