Search code examples
reactjsreact-hooksaddeventlistenerevent-listeneruse-effect

react useEffect not cleaning up event listener


I tried following 2 methods to remove event handler but both don't seem to work

Solution 1:

  const keyBindSearch = useCallback(e => {
    if ((e.metaKey && e.key === 'f') || (e.ctrlKey && e.key === 'f')) {
      e.preventDefault()
      console.log('CTRL F')
    }
  }, [])
  useEffect(() => {
    document.addEventListener('keydown', keyBindSearch)

    return () => {
      console.log('REMOVE')
      document.removeEventListener('keydown', keyBindSearch)
    }
  }, [])

Solution 2:

useEffect(() => {
    const keyBindSearch = e => {
      if ((e.metaKey && e.key === 'f') || (e.ctrlKey && e.key === 'f')) {
        e.preventDefault()
        console.log('CTRL F')
      }
    }
    document.addEventListener('keydown', keyBindSearch)

    return () => {
      console.log('REMOVE')
      document.removeEventListener('keydown', keyBindSearch)
    }
  }, [])

I see REMOVE in console so clean-up function from useEffect is definitely firing but event listener is not deleted and still logs CTRL F even after clean-up function is called.

What am I doing wrong?


Solution

  • There is nothing wrong with Solution 2 at least. Remember, the eventListener will be removed when the element is removed and not rendered again (otherwise the useEffect will bind the eventListener again). See my sample, when you remove the component, there is no CTRL F logged: https://codesandbox.io/s/epic-chatelet-e9qpv?file=/src/App.js