如何在不重复触发的情况下更新 useEffect 中的卸载处理程序?
How to update the unmount handler in a useEffect without firing it repeatedly?
今天,另一位开发人员向我提出了一个棘手的问题。她提出以下建议:
A.) 她想在模式关闭时触发一个事件。
B.) 她不希望事件在任何其他时间触发。
C.) 事件必须与组件状态保持同步。
一个基本的例子是这样的:
const ModalComponent = () => {
const [ eventData, setEventData ] = useState({ /* default data */ });
useEffect(() => {
return () => {
// happens anytime dependency array changes
eventFire(eventdata);
};
}, [eventData]);
return (
<>
// component details omitted, setEventData used in here
</>
);
};
目的是当模式关闭时触发事件。但是,用户与模式的交互会导致状态更新,从而更改 eventData
的值。这就引出了问题的核心:
- 将
eventData
排除在 useEffect
依赖项数组之外会导致它仅在模式关闭时触发,但该值已过时。这是组件安装时的值。
- 将
eventData
放在 useEffect
依赖项数组中会导致事件反复触发,只要数据发生变化并且组件重新呈现和更新 useEffect
.
解决这个问题的方法是什么?您如何访问最新数据,但仅在卸载时对其进行操作?
将 eventData
存储在参考文献中
const [eventData, setEventData] = useState({ /* default data */ });
const ref = useRef();
ref.current = eventData;
useEffect(() => () => eventFire(ref.current), []);
这将使该值始终保持最新,因为它不会被锁定到函数闭包中,并且无需在每次 eventData
更改时触发效果。
此外,您可以将此逻辑提取到自定义挂钩中。
function useStateMonitor(state) {
const ref = useRef();
ref.current = state;
return () => ref.current;
}
用法是这样的
const [eventData, setEventData] = useState({ /* default data */ });
const eventDataMonitor = useStateMonitor(eventData);
useEffect(() => () => eventFire(eventDataMonitor()), []);
这是一个working example
今天,另一位开发人员向我提出了一个棘手的问题。她提出以下建议:
A.) 她想在模式关闭时触发一个事件。
B.) 她不希望事件在任何其他时间触发。
C.) 事件必须与组件状态保持同步。
一个基本的例子是这样的:
const ModalComponent = () => {
const [ eventData, setEventData ] = useState({ /* default data */ });
useEffect(() => {
return () => {
// happens anytime dependency array changes
eventFire(eventdata);
};
}, [eventData]);
return (
<>
// component details omitted, setEventData used in here
</>
);
};
目的是当模式关闭时触发事件。但是,用户与模式的交互会导致状态更新,从而更改 eventData
的值。这就引出了问题的核心:
- 将
eventData
排除在useEffect
依赖项数组之外会导致它仅在模式关闭时触发,但该值已过时。这是组件安装时的值。 - 将
eventData
放在useEffect
依赖项数组中会导致事件反复触发,只要数据发生变化并且组件重新呈现和更新useEffect
.
解决这个问题的方法是什么?您如何访问最新数据,但仅在卸载时对其进行操作?
将 eventData
存储在参考文献中
const [eventData, setEventData] = useState({ /* default data */ });
const ref = useRef();
ref.current = eventData;
useEffect(() => () => eventFire(ref.current), []);
这将使该值始终保持最新,因为它不会被锁定到函数闭包中,并且无需在每次 eventData
更改时触发效果。
此外,您可以将此逻辑提取到自定义挂钩中。
function useStateMonitor(state) {
const ref = useRef();
ref.current = state;
return () => ref.current;
}
用法是这样的
const [eventData, setEventData] = useState({ /* default data */ });
const eventDataMonitor = useStateMonitor(eventData);
useEffect(() => () => eventFire(eventDataMonitor()), []);
这是一个working example