I’m creating a custom cursor by dynamically appending a div element in the useEffect hook when the component mounts and is set to follow the mouse using event listeners. However, two divs are being rendered—one properly follows the mouse, while the other stays at the top-left corner of the viewport.
import { useRef, useEffect, useState } from "react"
function Pcanvas({width, height, pixelSize}){
const [canvasColor, setCanvasColor] = useState("#dcdcdc")
const [pencilSize, setPencilSize] = useState(pixelSize)
const canvasRef = useRef(null)
var mousePressed = false
function mouseCursor(){
const cursor = document.createElement("div")
cursor.className = 'cursor'
cursor.style.backgroundColor = 'black'
cursor.style.width = pencilSize + 'px'
cursor.style.height = pencilSize + 'px'
cursor.style.position = 'absolute';
cursor.style.display = 'block';
cursor.style.zIndex = 999;
cursor.style.pointerEvents = 'none';
document.body.appendChild(cursor)
console.log(cursor.getBoundingClientRect().y)
}
function handleMouseMov(event){
const cursor = document.getElementsByClassName('cursor')[0]
console.log(cursor.getBoundingClientRect().y)
if(cursor){
cursor.style.top = event.clientY-(pencilSize/2) + 'px'
cursor.style.left = event.clientX-(pencilSize/2) + 'px'
}
}
function handleMouseLeave(event){
const cursor = document.getElementsByClassName('cursor')[0]
if(cursor){
cursor.style.display = 'none'
}
}
function handleMouseEnter(event){
const cursor = document.getElementsByClassName('cursor')[0]
if(cursor){
cursor.style.display = 'block'
}
}
useEffect(() => {
const canvas = canvasRef.current
mouseCursor()
document.body.addEventListener('mouseenter', handleMouseEnter)
document.body.addEventListener('mousemove', handleMouseMov)
document.body.addEventListener('mouseleave', handleMouseLeave)
return(() => {
document.body.removeEventListener('mouseenter', handleMouseEnter)
document.body.removeEventListener('mousemove', handleMouseMov)
document.body.removeEventListener('mouseleave', handleMouseLeave)
})
}, [pencilSize])
return(
<></>
)
}
export default Pcanvas
2
Answers
You should avoid
createElement
and especiallygetElementsByClassName
when using React.Let the component self render the
div
, then use anuseRef
to change any styling when needed.To fix this, you should ensure that only one cursor is created. You can create the cursor once inside the useEffect hook when the component is mounted and remove it only when the component unmounts. Here’s an updated version of your code: