Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Why does this simple React component throw an error when I try to run it?

This is a trivial analog clock that seems simple enough. However, it seems to fail at line 7 with "TypeError: Cannot read properties of null (reading ‘style’)". I’ve also tried the setAttribute() method and get the same thing. How do I dynamically update the rotation every second?

export const Analog = () => {
  function setDate() {
    let secondHand = document.querySelector(".second-hand");
    const now = new Date();
    const seconds = now.getSeconds();
    const secondsDegrees = (seconds / 60) * 360 + 90;
    secondHand.style.transform = `rotate(${secondsDegrees}deg)`;
  }
  setInterval(setDate, 1000);

  return (
    <svg id="clock" className="min-w-full min-h-full" viewBox="0 0 100 100">
      <circle id="face" cx="50" cy="50" r="50" />
      <g id="hands">
        <circle id="center" cx="50" cy="50" r="2" fill="white" />
        <line
          id="secondHand"
          className="second-hand"
          x1="50"
          y1="50"
          x2="50"
          y2="0"
        />
      </g>
    </svg>
  );
};

>Solution :

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

In react you should almost never need to do direct dom manipulation, and definitely not for the scenario you have here. Instead, you should use a state variable to track how much it’s supposed to be rotated, and use that variable in the render output. Additionally, you don’t want to set an interval in the body of your component, as that will result in an ever increasing number of intervals. useEffect should be used instead.

export const Analog = () => {
  const [secondsDegrees, setSecondsDegrees] = useState(0);

  useEffect(() => {
    const id = setInterval(() => {
      const now = new Date();
      const seconds = now.getSeconds();
      setSecondsDegrees((seconds / 60) * 360 + 90);
    }, 1000);
    return () => clearInterval(id);
  }, []);

 return (
    <svg id="clock" className="min-w-full min-h-full" viewBox="0 0 100 100">
      <circle id="face" cx="50" cy="50" r="50" />
      <g id="hands">
        <circle id="center" cx="50" cy="50" r="2" fill="white" />
        <line
          id="secondHand"
          className="second-hand"
          style={{ transform: `rotate(${secondsDegrees}deg)` }}
          x1="50"
          y1="50"
          x2="50"
          y2="0"
        />
      </g>
    </svg>
  );
}
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading