user12048508
user12048508

Reputation:

Custom Mouse Cursor using React: Uncaught TypeError: Cannot read property 'clientWidth' of null

Hi I was playing around with creating a custom cursor in react. The cursor works fine, however a few seconds later after a few scrolls or changing pages, i get the following error: Uncaught TypeError: Cannot read property 'clientWidth' of null.

  //follows the cursor
  const customRef = React.useRef(null)
   
  React.useEffect(() => {
  document.addEventListener('mousemove', (e) => {
    const { clientX, clientY } = e
    const mouseX = clientX - customRef.current.clientWidth / 2
    const mouseY = clientY - customRef.current.clientHeight / 2
  customRef.current.style.transform = `translate3d(${mouseX}px, ${mouseY}px, 0)`
  })
  }, [])

  return (
    <div className="app-cursor" ref={customRef} />

  )
}

export default CustomCursor

Here's the CSS:

.app-cursor {
  z-index: 100;
  border-radius: 50%;
  width: 60px;
  height: 60px;
  border: 1px solid rgb(168, 163, 163);
  pointer-events: none;
  overflow: hidden; 
  transform: translate3d(0, 0, 0);
  position: fixed;
}

Any help would be appreciated.

Thanks in advance.

Upvotes: 3

Views: 1065

Answers (1)

Vencovsky
Vencovsky

Reputation: 31713

The reason why you get the error is because you add the event listener but never removes it and in a certain point of your application, you unmount the element your are passing the ref, and when trying to access that ref, it doesn't exists.

You need to remove the event listener in the cleanup effect of the useEffect.

const CustomCursor = () => {
    //follows the cursor
    const customRef = React.useRef(null)
   
    useEffect(() => {
      const onMouseMove = (e) => {
        const { clientX, clientY } = e
        const mouseX = clientX - customRef.current.clientWidth / 2
        const mouseY = clientY - customRef.current.clientHeight / 2
        customRef.current.style.transform = `translate3d(${mouseX}px, ${mouseY}px, 0)`
      }
      // add the event listener
      document.addEventListener('mousemove', onMouseMove)
      // cleanup function
      return () => {
        // remove the event listener when the component unmounts
        document.removeEventListener('mousemove', onMouseMove)
      }
    }, [])
  
    return (
      <div className="app-cursor" ref={customRef} />
    )
}

Upvotes: 2

Related Questions