score:0

Accepted answer

You're voilating several rules while using React Component and hooks, here's a much standard version of your code:

// Put the variables outside to make sure they won't reset while component refresh
let mouseX = 0
let mouseY = 0
let ballX = 0
let ballY = 0
let speed = 0.2

const Button = props => {
    const ballRef = React.useRef(null);

    // use useCallback to make sure this function won't create multiple copies when refreshed
    const animate = React.useCallback(() => {
        // Make sure the ballRef is created, at the first run, the ball ref is still null
        if(ballRef && ballRef.current) {
            let distX = mouseX - ballX
            let distY = mouseY - ballY
            ballX = ballX + distX * speed
            ballY = ballY + distY * speed
            ballRef.current.style.left = ballX + "px"
            ballRef.current.style.top = ballY + "px"
        }

        requestAnimationFrame(animate)
    }, [ballRef, mouseX, mouseY, ballX, ballY]);

    // This make sure the function inside only runs when the component is mounted
    React.useEffect(()=>{
        const onMouseMove = event => {
            mouseX = event.pageX;
            mouseY = event.pageY;
        };

        document.addEventListener("mousemove", onMouseMove);

        animate();

        // When the component is unmount, remove the listener
        return () => document.removeEventListener("mousemove", onMouseMove);
    }, []);

    return (
        <div ref={ballRef} >Button</div>
    )
}

export default Button

score:0

You need to set animate() in useEffect

useEffect(() => {
    animate();
}, []);

Related Query

More Query from same tag