组件卸载时
和原来的componentWillUnmount一样的用法, 在useEffect return里调用就可以了
useEffect(() => {
window.addEventListener('click', clickFunc);
return () => {
window.removeEventListener('click', clickFunc);
};
});
组件使用过程中
当组件不涉及重新渲染时了, 像这么写完全没问题, 点击Remove Click to Console之后监听取消.
import React, { useState } from "react";
const App = () => {
// const [state, setState] = useState(0)
const handleAddListening = () => {
window.addEventListener('click', clickFunc)
// setState(state + 1)
}
const clickFunc = () => {
console.log('clicking')
}
const handleRemoveListening = () => {
window.removeEventListener('click', clickFunc)
}
return (
<div className="App">
<div onClick={handleAddListening}>
Click to Console
</div>
<div onClick={handleRemoveListening}>
Remove Click to Console
</div>
</div>
);
}
现在我们把以上代码中的注释取消掉, 加入useState
导致组件再次渲染, 此时发现无论如何点击Remove Click to Console
, 点击事件发生时, 会一直console clicking
.
甚至再次单击Click to Console
触发绑定事件, 发现会同时console clicking
两次;
再再次单击, console次数会继续累计增加.
这是因为每次触发组件再次渲染, clickFunc
作为组件内的方法, 会跟着一同再次渲染, 并且在内存里, 再次渲染出的 clickFunc !== 前clickFunc
.
所以removeEventListener
无法解除绑定, 再次addEventListener
则会绑定一个新方法.
解决方案:
const clickFunc = useCallback(() => {
console.log("clicking");
}, []);
使用无依赖的useCallback
解决clickFunc
的重新渲染问题