我有一个组件Example,当本地状态display更改为false时,要清除事件侦听器,当show prop is E 110trueE 211时,display设置为true,反之亦然。
代码:
const Example = ({ show, onClose }) => {
const [display, setDisplay] = useState(false);
const handleClick = (e) => {
onClose();
console.log(display);
};
useEffect(() => {
if (display) {
document.addEventListener('click', handleClick);
} else {
document.removeEventListener('click', handleClick);
}
}, [display, handleClick]);
useEffect(() => {
if (show) {
setDisplay(show);
} else {
setDisplay(false);
}
}, [show]);
return <div>{display && <p>Hi</p>}</div>;
};问题:
组件无法清除事件侦听器,因为每次调用renders.
handleClick()时都会生成函数handleClick()的新引用,它将display记录为true.
E 1337-8鼠标单击E 234,控制台中的日志<代码>E 135计数<代码>E 2367-8K.>
我在这里做错什么了?谢谢:)
发布于 2020-04-26 16:56:18
为了在useEffect中清理,返回效果中的函数。该函数将在每次效果重新运行和组件卸载时调用。
之所以允许正确删除事件侦听器,是因为useEffect在handleClick函数的当前版本上创建了一个闭包。它允许清理功能具有相同的引用,这样就可以正确地清除它。它在最初的版本中没有工作,因为每次useEffect重新运行时,都会关闭一个新版本的handleClick,然后使用新版本尝试清理。
useEffect(() => {
if (!display) {
return;
}
document.addEventListener('click', handleClick);
return () => document.removeEventListener('click', handleClick);
}, [display, handleClick]);您可以通过对handleClick函数使用ref来进一步减少这种影响的发生。
例如,它是最基本的。尽管您可以轻松地将一些引用和额外的使用效果抽象到一个单独的钩子上。
const handleClickRef = useRef(handleClick);
useEffect(()=>{
handleClickRef.current = handleClick;
},[handleClick])
useEffect(() => {
if (!display) {
return;
}
const funct = (evt)=>handleClickRef.current(evt);
document.addEventListener('click',funct);
return () => document.removeEventListener('click', funct);
}, [display]);https://stackoverflow.com/questions/61444561
复制相似问题