'How to add a 'mousemove' event listener to a component Cursor which is moved with the cursor pointer in ReactJS?

import React, {Component} from 'react';

class Cursor extends Component {
    state = {
        left: 0,
        top: 0
    }
    render() {
        return (
            <div className='cursor'></div>
        )
    }
}

document.addEventListener('mousemove', (e) => {
    const cursor = document.getElementsByClassName('cursor')[0];
    cursor.setAttribute('style','top:'+e.pageY+'px; left:'+ e.pageX+'px;');
});

export default Cursor;

This code is not updating the state of the react component Cursor. I don't know how to do it. So, I did it in vanilla JavaScript. How can I do it clearly by updating state?



Solution 1:[1]

import React, {Component} from 'react';

class Cursor extends Component {
    state = {
        left: 0,
        top: 0
    }
    componentDidMount() {
        document.addEventListener('mousemove', (e) => {
            this.setState({left: e.pageX, top: e.pageY});
        });
    }
    render() {
        return (
            <div style={{left: this.state.left, top: this.state.top}} className='cursor'></div>
        )
    }
}

export default Cursor;

This worked...

Solution 2:[2]

with hook component :

import React, { useState } from 'react';


export default function Cursor() { 

  const [MousePosition, setMousePosition] = useState({
      left: 0,
      top: 0
  })

  function handleMouseMove(ev) { setMousePosition({left: ev.pageX, top: ev.pageY}); }

  return (
    <div 
      onMouseMove={(ev)=> handleMouseMove(ev)}
      style={{left:MousePosition.left , top: MousePosition.top}}
    > </div>
  )

}

Solution 3:[3]

This should work:

import React, { Component } from 'react';

class Cursor extends Component {
  state = {
    left: 0,
    top: 0
  }

  handleCursor = (e) => {
    const cursor = document.getElementsByClassName('cursor')[0];     
    cursor.setAttribute('style','top:'+e.pageY+'px; left:'+ e.pageX+'px;');
  }

  render() {
    return (
      <div 
        onMouseMove={ this.handleCursor }
        className='cursor'>
      </div>
    )
  }
}

export default Cursor;

If you want to use event listeners, this should also work for you:

import React, { Component } from 'react';

class Cursor extends Component {
  state = {
    left: 0,
    top: 0
  }

  componentDidMount() {
    // When the component is mounted, add your DOM listener.
    document.addEventListener("mousemove", this.handleCursor);
  }

  componentWillUnmount() {
    // Make sure to remove the DOM listener when the component is unmounted.
    document.removeEventListener("mousemove", this.handleCursor);
  }

  handleCursor = (e) => {
    const cursor = document.getElementsByClassName('cursor')[0];     
    cursor.setAttribute('style','top:'+e.pageY+'px; left:'+ e.pageX+'px;');
  }

  render() {
    return (
      <div className='cursor'></div>
    )
  }
}

export default Cursor;

Solution 4:[4]

Here's a generic hook you can attach to any React component based on caio-trianahotmailcom's answer:

import { useCallback, useRef, useState } from "react";

const useMousePosition = () => {
  const [mousePosition, setMousePosition] = useState({
    left: 0,
    top: 0,
  });

  const handleMouseMove = useCallback(
    (e) =>
      setMousePosition({
        left: e.pageX,
        top: e.pageY,
      }),
    []
  );

  const ref = useRef();

  const callbackRef = useCallback(
    (node) => {
      if (ref.current) {
        ref.current.removeEventListener("mousemove", handleMouseMove);
      }

      ref.current = node;

      if (ref.current) {
        ref.current.addEventListener("mousemove", handleMouseMove);
      }
    },
    [handleMouseMove]
  );

  return [callbackRef, mousePosition];
};

export default useMousePosition;

And this is how you use it:

/**
 * @function App
 * @returns JSX.Element
 */

const App = () => {
  const [ref, mousePosition] = useMousePosition();

  useEffect(() => {
    // do something with the mouse position values here
    console.log(mousePosition);
  }, [mousePosition]);
  
  return (<div className="App" ref={ref} />);
};

export default App;

Solution 5:[5]

import { useEffect } from "react";

const Component = ()??{
    const [state, setState] = useState({ left: 0, top: 0 });
    useEffect(() => {
        document.addEventListner('mousemove', (e) => {
            setState( {left: e.pageX, top: e.pageY });  
        })
    }, [])

    return (
        <div style={state}> hihi </div>
    );
}

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 Ranjith
Solution 2 caio_trianahotmailcom
Solution 3
Solution 4
Solution 5