Clean up event listeners in useEffect

The resize listener that stayed alive after the component was gone, and how to not do that.

SNP 099 #A51 Filed js react

Return a function from the effect; React calls it before the next run and when the component unmounts:

jsx
useEffect(() => {
  const onResize = () => setWidth(window.innerWidth)
  window.addEventListener('resize', onResize)

  return () => window.removeEventListener('resize', onResize)
}, [])

The handler has to be the same function in both calls, so define it once inside the effect. An inline arrow in removeEventListener removes nothing.

With an AbortController you can clean up several listeners at once:

jsx
useEffect(() => {
  const controller = new AbortController()
  const { signal } = controller
  window.addEventListener('resize', onResize, { signal })
  window.addEventListener('scroll', onScroll, { signal })

  return () => controller.abort()
}, [])