我们必须停止思考组件生命周期方法(即componentDidMount)。我们必须开始思考效果。 React 效果不同于旧式的类生命周期方法。
默认情况下,效果会在每个渲染周期后运行,但可以选择退出此行为。要选择退出,您可以定义依赖项,这意味着仅在对其中一个依赖项进行更改时才会执行效果。
如果您明确定义效果没有依赖关系,则该效果仅在第一个渲染周期之后运行一次。
第一种解决方案(使用 ESLint 投诉)
因此,您的示例的第一个解决方案如下:
function MyComponent() {
const loadDataOnlyOnce = () => {
console.log("loadDataOnlyOnce");
};
useEffect(() => {
loadDataOnlyOnce(); // this will fire only on first render
}, []);
return (...);
}
但是 React Hooks ESLint 插件会抱怨这样的事情:
React Hook useEffect has missing dependency: loadDataOnlyOnce. Either include it or remove the dependency array.
起初这个警告看起来很烦人,但请不要忽视它。它可以帮助您更好地编码。
第二个解决方案(正确的方法,如果依赖不依赖于组件)
如果我们将loadDataOnlyOnce 添加到依赖数组中,我们的效果将在每个渲染周期后运行,因为loadDataOnlyOnce 的引用在每次渲染时都会发生变化,因为函数被销毁(垃圾收集)和一个新函数已创建,但这正是我们不想要的。
我们必须在渲染周期中保持loadDataOnlyOnce 的相同引用。
所以只需移动上面的函数定义:
const loadDataOnlyOnce = () => {
console.log("loadDataOnlyOnce");
};
function MyComponent() {
useEffect(() => {
loadDataOnlyOnce(); // this will fire only on first render
}, []);
return (...);
}
第三种解决方案(正确的方法,如果依赖依赖于组件)
如果效果的依赖(loadDataOnlyOnce),依赖于组件(需要道具或状态),有React的内置useCallback-Hook。
useCallback-Hook 的基本意义是在渲染周期内保持函数的引用相同。
function MyComponent() {
const [state, setState] = useState("state");
const loadDataOnlyOnce = useCallback(() => {
console.log(`I need ${state}!!`);
}, [state]);
useEffect(() => {
loadDataOnlyOnce(); // // this will fire only when loadDataOnlyOnce-reference changes
}, [loadDataOnlyOnce]);
return (...);
}