'How to correctly get mouse events in react without re-rendering the parent component

I am trying to make a hook that returns the clientX and clientY values when the mouse moves on the screen. My hook looks like this -

useMouseMove hook

const useMouseMove = () => {
    const [mouseData, setMouseData] = useState<[number, number]>([0, 0])

    useEffect(() => {
        const handleMouse = (e: MouseEvent) => {
            setMouseData([e.clientX, e.clientY])
        }

        document.addEventListener("mousemove", handleMouse)

        return () => {
            document.removeEventListener("mousemove", handleMouse)
        }
    }, [])

    return mouseData
}

And I'm using it in another component like so,

Usage in component

const SomeComponent = () => {
    const mouseData = useMouseMoveLocation()

    console.log("Rendered") // I want this to be rendered only once

    useEffect(() => {
        // I need to use the mouseData values here
        console.log({ mouseData })
    }, [mouseData])

    return <>{/* Some child components */}</>
}

I need to use the mouseData values from the useMouseMove hook in the parent component (named SomeComponent in the above example) without re-rendering the entire component every time the mouse moves across the screen. Is there a correct way to do this to optimise for performance?



Solution 1:[1]

If you're not going to be rendering this component, then you can't use a useEffect. useEffect's only get run if your component renders. I think you'll need to run whatever code you have in mind in the mousemove callback:

const useMouseMove = (onMouseMove) => {
    useEffect(() => {
        document.addEventListener("mousemove", onMouseMove)

        return () => {
            document.removeEventListener("mousemove", onMouseMove)
        }
    }, [onMouseMove])
}

const SomeComponent = () => {
  useMouseMove(e => {
    // do something with e.clientX and e.clientY
  });
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Nicholas Tower