我们必须停止思考组件生命周期方法(即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 (...);
}
第三种解决方案(正确的方法,如果依赖项依赖于组件)
如果 effect ( loadDataOnlyOnce
) 的依赖依赖于组件(需要 props 或 state),则有 React 的内置useCallback
-Hook。
-Hook的基本意义useCallback
是在渲染周期内保持函数的引用相同。
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 (...);
}