问题描述
我在 useEffect
中添加了一个事件监听器.由于 useEffect 第二个参数([]
),它在第一次重新渲染后运行一次.然后我尝试在 useEffect
之外(在 handleSearch 函数中)删除它,但它不起作用.我怀疑它与函数作用域有关,但并不完全理解.也许有解决方法?
I add an event listener inside useEffect
. It runs once after first rerender due to the useEffect second argument([]
). Then I try to remove it outside useEffect
(in handleSearch function) but it doesn't work. I suspect it has something to do with function scopes but don't understand it fully. Maybe there is a workaround?
const handleSearch = () => {
window.removeEventListener('resize', setPageHeightWrapper);
};
const [pageHeight, setPageHeight] = useState(0);
function setPageHeightWrapper() { setPageHeight(window.innerHeight); };
useEffect(() =>{
window.addEventListener('resize', setPageHeightWrapper);
return () => {
window.removeEventListener('resize', setPageHeightWrapper);
};
}, []);
推荐答案
它不工作的原因是因为 setPageHeightWrapper
定义了一个内联函数,当组件重新渲染一个新实例时它被创建,在清除事件侦听器时,您需要传递在设置侦听器时传递的相同方法.
The reason it doesn't work is because setPageHeightWrapper
is defined an inline function and when the component re-renders a new instance of it is created and while clearing an event listener you need to pass the same method which was passed while setting the listener.
另一方面,当调用 useEffect 钩子时,它会从其闭包中获取函数引用,并使用相同的引用来清除侦听器.
On the other hand, when a useEffect hook is called it, gets the function reference from its closure and it uses the same reference to clear the listener.
使 removeListener 在 useEffect 之外工作的一种方法是使用 useCallback
钩子
A way to make the removeListener work outside of useEffect is to use useCallback
hook
const handleSearch = () => {
window.removeEventListener('resize', memoHeightWrapper);
};
const [pageHeight, setPageHeight] = useState(0);
const memoHeightWrapper = useCallback(() => {
setPageHeight(window.innerHeight);
})
useEffect(() =>{
window.addEventListener('resize', memoHeightWrapper);
return () => {
window.removeEventListener('resize', memoHeightWrapper);
};
}, []);
这篇关于无法删除 useEffect 之外的事件侦听器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!