const [a, seta] = useState(1)
const [loading, setLoading] = useState(false) //用于等到某个异步操作返回结果后再允许再次触发fn函数
useEffect(() => {
document.addEventListener('LazShake.Event.onShakeOnce', () => {
fn('listener');
});
}, []);
useEffect(() => {
setTimeout(() => {
seta(2)
},1000)
},[])
const fn = (from) => {
if (loading) { return }
setLoading(true);
const time=new Date(Date.now())
console.log(11111, 'from: ', from, "min: ",time.getMinutes(),"sec: ",time.getSeconds(), 'a: ',a);
setTimeout(() => {
setLoading(false)
}, 2000)
};
两种方式触发fn, 监听事件:addEventListener; 点击任意事件触发fn:click
发现:监听事件触发的fn,变量a不更新, loading参数不更新, 监听事件的fn为第一次渲染时候的快照,里面的参数后续不更新
如果将上述监听事件改为
const triggerFn = useCallback(() => {
fn('listener');
}, [a]);
useEffect(() => {
document.addEventListener('LazShake.Event.onShakeOnce', triggerFn);
return () => {
document.removeEventListener('LazShake.Event.onShakeOnce', triggerFn)
}
}, [triggerFn]);
则能保证监听事件触发的fn能拿到最新的变量a
由于a是在一秒后更新了一次,因此addEventListener函数也只更新了一次,fn里面的loading变量也只更新了一次, 后续loading的更新对fn参数无效, 所以triggerFn依赖变量a还不够,还需要依赖loading变量