koo*_*koo 22 reactjs react-hooks
如果要限制useEffect仅在组件安装时运行,则可以添加useEffectwith的第二个参数[]。
useEffect(() => {
// ...
}, []);
Run Code Online (Sandbox Code Playgroud)
但是,如何使useEffect该组件仅在组件被更新(除了初始安装)的那一刻才运行?
Shu*_*tri 43
如果要运行useEffect以仅在除初始安装之外的更新上运行,则可以利用useRef跟踪带有useEffect第二个参数的initialMount 。
const isInitialMount = useRef(true);
useEffect(() => {
if (isInitialMount.current) {
isInitialMount.current = false;
} else {
// Your useEffect code here to be run on update
}
});
Run Code Online (Sandbox Code Playgroud)
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
};
Run Code Online (Sandbox Code Playgroud)
我真的很喜欢Shubham的回应,所以我把它做成了自定义的Hook
/**
* A custom useEffect hook that only triggers on updates, not on initial mount
* Idea stolen from: /sf/answers/3855307291/
* @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 {
effect();
}
}, dependencies); // eslint-disable-line react-hooks/exhaustive-deps
}
Run Code Online (Sandbox Code Playgroud)
const [mounted, setMounted] = useRef(false)
useEffect(() => {
if(!mounted) return setMounted(true)
...
})
Run Code Online (Sandbox Code Playgroud)
export const useMounted = () => {
const mounted = useRef(false)
useEffect(() => {
mounted.current = true
return () => {
mounted.current = false
}
}, [])
return () => mounted.current
}
Run Code Online (Sandbox Code Playgroud)
const Component = () => {
const mounted = useMounted()
useEffect(() => {
if(!mounted()) return
...
})
}
Run Code Online (Sandbox Code Playgroud)
您可以通过将状态设置为非布尔初始值(如空值)来解决这个问题:
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]);
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
5231 次 |
| 最近记录: |