如果我们想限制useEffect
只在组件挂载时运行,我们可以添加useEffect
with 的第二个参数[]
。
useEffect(() => {
// ...
}, []);
但是我们如何才能让useEffect
除了初始挂载之外的组件更新的那一刻才运行呢?
如果我们想限制useEffect
只在组件挂载时运行,我们可以添加useEffect
with 的第二个参数[]
。
useEffect(() => {
// ...
}, []);
但是我们如何才能让useEffect
除了初始挂载之外的组件更新的那一刻才运行呢?
如果您希望 useEffect 仅在除初始安装之外的更新上运行,您可以使用 ofuseRef
来跟踪 initialMountuseEffect
而不带第二个参数。
const isInitialMount = useRef(true);
useEffect(() => {
if (isInitialMount.current) {
isInitialMount.current = false;
} else {
// Your useEffect code here to be run on update
}
});
我真的很喜欢 Shubham 的回应,所以我做了一个定制的 Hook
/**
* A custom useEffect hook that only triggers on updates, not on initial mount
* @param {Function} effect
* @param {Array<any>} dependencies
*/
export default function useUpdateEffect(effect, dependencies = []) {
const isInitialMount = useRef(true);
useEffect(() => {
if (isInitialMount.current) {
isInitialMount.current = false;
} else {
return effect();
}
}, dependencies);
}
Shubham 和 Mario 都提出了正确的方法,但是代码仍然不完整,没有考虑以下情况。
effect
函数可能有一个从它返回的清理函数,它永远不会被调用 下面分享一个更完整的代码,其中涵盖了上述两种缺失的情况:
import React from 'react';
const useIsMounted = function useIsMounted() {
const isMounted = React.useRef(false);
React.useEffect(function setIsMounted() {
isMounted.current = true;
return function cleanupSetIsMounted() {
isMounted.current = false;
};
}, []);
return isMounted;
};
const useUpdateEffect = function useUpdateEffect(effect, dependencies) {
const isMounted = useIsMounted();
const isInitialMount = React.useRef(true);
React.useEffect(() => {
let effectCleanupFunc = function noop() {};
if (isInitialMount.current) {
isInitialMount.current = false;
} else {
effectCleanupFunc = effect() || effectCleanupFunc;
}
return () => {
effectCleanupFunc();
if (!isMounted.current) {
isInitialMount.current = true;
}
};
}, dependencies); // eslint-disable-line react-hooks/exhaustive-deps
};
您可以通过将状态设置为非布尔初始值(如空值)来解决它:
const [isCartOpen,setCartOpen] = useState(null);
const [checkout,setCheckout] = useState({});
useEffect(() => {
// check to see if its the initial state
if( isCartOpen === null ){
// first load, set cart to real initial state, after load
setCartOpen( false );
}else if(isCartOpen === false){
// normal on update callback logic
setCartOpen( true );
}
}, [checkout]);
从 Subham 的回答中获得帮助此代码只会针对特定项目更新运行,而不是在每次更新时运行,也不会在组件初始安装时运行。
const isInitialMount = useRef(true); //useEffect to run only on updates except initial mount
//useEffect to run only on updates except initial mount
useEffect(() => {
if (isInitialMount.current) {
isInitialMount.current = false;
} else {
if(fromScreen!='ht1' && appStatus && timeStamp){
// let timeSpentBG = moment().diff(timeStamp, "seconds");
// let newHeatingTimer = ((bottomTab1Timer > timeSpentBG) ? (bottomTab1Timer - timeSpentBG) : 0);
// dispatch({
// type: types.FT_BOTTOM_TAB_1,
// payload: newHeatingTimer,
// })
// console.log('Appstaatus', appStatus, timeSpentBG, newHeatingTimer)
}
}
}, [appStatus])