0

I'm trying to convert a React Class Component but have failed after a day full of failed attempts.

The current class component looks like this:

class NeonCursor extends React.Component {
  constructor(props) {
    super(props);

    this.state = { top: 0, left: 0 };
  }

  componentDidMount() {
    document.addEventListener('mousemove', handleMouseMove);
    document.documentElement.classList.add('no-cursor');
  }

  componentWillUnmount() {
    document.documentElement.classList.remove('no-cursor');
    document.removeEventListener('mousemove', handleMouseMove);
  }

  handleMouseMove = (e) => {
    this.setState({
      top: e.pageY,
      left: e.pageX,
    });
  };

  render() {
    return (
      <img
        src="https://code.s3.yandex.net/web-code/react/cursor.svg"
        width={30}
        style={{
          position: 'absolute',
          top: this.state.top,
          left: this.state.left,
          pointerEvents: 'none',
        }}
      />
    );
  }
}

My current attempt looks like this:

function NeonCursor(props) {
  
  const [top, setTop] = React.useState(top: 0);
  const [left, setLeft] = React.useState(left: 0);
  
  React.useEffect(() => {
    document.addEventListener('mousemove', handleMouseMove);
    document.documentElement.classList.add('no-cursor');
    
    return () => {
      document.documentElement.classList.remove('no-cursor');
    document.removeEventListener('mousemove', handleMouseMove);
    }
  }); 
  
  return (
      <img
        src="https://code.s3.yandex.net/web-code/react/cursor.svg"
        width={30}
        style={{
          position: 'absolute',
          top: setTop,
          left: setLeft,
          pointerEvents: 'none',
        }}
      />
    );
  
  function handleMouseMove = (e) => {
    setState({
      setTop: e.pageY,
      setLeft: e.pageX,
    });
  };
  
}

So far, I have done the following steps:

  1. Rename the class component by using function() naming
  2. Remove the class constructor
  3. Replace the state in the constructor by using the useState hook
  4. Pass the ComponentDidMount and ComponentWillUnmount methods to a React.useEffect hook via callbacks.
  5. Replace all this. syntax from the code.
  6. Convert the handleMouseMove method to a function.

However my code is not working and always get a "Script error." message.

What would be the proper approach to this conversion?

I have prepared codepens for: Original code: https://codepen.io/aegisnull/pen/YzLaxQJ My attempt: https://codepen.io/aegisnull/pen/xxjWLXp

1
  • Those codepens look the same to me. Am I overlooking something obvious? Commented Sep 30, 2022 at 1:35

2 Answers 2

1

First, you define the useState hook in wrong way.

const [top, setTop] = React.useState(top: 0);
const [left, setLeft] = React.useState(left: 0);

It should be :

const [top, setTop] = React.useState(0); // 0 is initial/default value of state called top
const [left, setLeft] = React.useState(0);

Second, your handler also have a mistake

function handleMouseMove = (e) => {
    setState({
      setTop: e.pageY,
      setLeft: e.pageX,
    });
};

react fc component is don't have setState that's why before react have a hooks it's called stateless component. And when you define your state [top, setTop],setTop is function to update the value of top. So your handleMouseMove should be:

function handleMouseMove = (e) => {
    setTop(e.pageY)
    setLeft(e.pageX)
};
Sign up to request clarification or add additional context in comments.

Comments

0

The main issues were your use of state and the location of the handleMouseMove function and the handleMouseMove function declaration.

Your state variables are called top and left and these are what you refer to when using the value (as per the style tag in your image). You update these using their associated set function i.e. setTop for updating top or setLeft for updating left (as shown in the handleMouseMove function). Their initial value is defined in the brackets. Since these are meant to store an x or y coordinate they are both numeric types.

The handleMouseMove function needed to move above the return statement to remain in scope and the declaration fixed.

Try this

function NeonCursor(props) {

    const [top, setTop] = React.useState(0);
  const [left, setLeft] = React.useState(0);
  
  React.useEffect(() => {
    document.addEventListener('mousemove', handleMouseMove);
    document.documentElement.classList.add('no-cursor');
    
    return () => {
      document.documentElement.classList.remove('no-cursor');
    document.removeEventListener('mousemove', handleMouseMove);
    }
  }); 

  const handleMouseMove = (e: any) => {
    console.log(e)
    setTop(e.pageY)
    setLeft(e.pageX)
  };
  
  return (
      <img
        src="https://code.s3.yandex.net/web-code/react/cursor.svg"
        alt="cursor"
        width={30}
        style={{
          position: 'absolute',
          top: top,
          left: left,
          pointerEvents: 'none',
        }}
      />
    );
  
  
}

export default NeonCursor;

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.