How do I window removeEventListener using React useEffect

前端 未结 2 530
小蘑菇
小蘑菇 2021-01-01 11:03

In React Hooks documents it is shown how to removeEventListener during the component\'s cleanup phase. https://reactjs.org/docs/hooks-reference.html#conditionally-firing-an-

相关标签:
2条回答
  • 2021-01-01 11:14

    You can put the handleKeyUp function inside of the function given to useEffect and only add the listener and return a cleanup function when collapsed is false.

    useEffect(() => {
      if (!collapsed) {
        function handleKeyUp(event) {
          switch (event.key) {
            case "Escape":
              setCollapsed(true);
              break;
          }
        }
    
        window.addEventListener("keyup", handleKeyUp);
        return () => window.removeEventListener("keyup", handleKeyUp);
      }
    }, [collapsed]);
    
    0 讨论(0)
  • 2021-01-01 11:39

    Tholle's answer may work, but it's bad practice to declare a function inside an if.

    It makes it harder to follow when the function is declared and when it is not. Also it can lead to bugs because functions are hoisted up.

    There's a neater way to fix it:

    By wrapping your event handler with the useCallback hook.

    const [collapsed, setCollapsed] = useState(true)
    
    const handleKeyUp = useCallback((event) => {
        if (event.key === "Escape") {
          setCollapsed(true)
        }
    }, [setCollapsed])
    
    useEffect(() => {
        if (!collapsed) {
            window.addEventListener("keyup", handleKeyUp)
        } else {
            window.removeEventListener("keyup", handleKeyUp)
        }
    
        return () => window.removeEventListener("keyup", handleKeyUp)
    }, [collapsed, handleKeyUp])
    
    • useCallback has a dependency on setCollapsed. This makes sure handleKeyUp is not redefined when the component rerenders (which always happens when state changes)
    • useEffect will conditionally add/remove the event listener, otherwise events will keep firing as long as the component is mounted.

    If you use a lot of event handlers in useEffect, there's a custom hook for that: https://usehooks.com/useEventListener/

    Here's the question posters example updated with my solution: https://codepen.io/publicJorn/pen/eYzwENN

    0 讨论(0)
提交回复
热议问题