简体   繁体   中英

Cannot remove an event listener outside useEffect

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);
  };
}, []);

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.

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.

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);
  };
}, []);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM