raj m
raj m

Reputation: 2023

useState doesn't work first time when given date in string while implementing stop watch

I have uploaded my code here in https://codesandbox.io/s/blissful-lehmann-o4thw?file=/src/Layout.tsx

I am trying to do a stopwatch. But working not as expected due to hook issue.

 const startTimer = async () => {
   setDisableStart(true);
   setDisableStop(false);
   const rightNowTime = await Date.now().toString();
   setCurrentTime(rightNowTime);
   interval = setInterval(() => {
     calculateTime();
   }, 1);
};

I can see problem with setCurrentTime(rightNowTime) is not updating current time

Please, somebody, suggest

Upvotes: 0

Views: 430

Answers (1)

Drew Reese
Drew Reese

Reputation: 202915

You are making things a bit more complicated than they need to be. I suggest storing only a start time and a current "tick" and compute the derived "state" of the minutes, seconds, and milliseconds between these two timestamps.

const App = () => {
  const [startTime, setStartTime] = useState<number>(0);
  const [currentTime, setCurrentTime] = useState<number>(0);

  // Store interval id in React ref
  const intervalRef = useRef<number | undefined>();

  const [disableStop, setDisableStop] = useState<boolean>(true);
  const [disableReset, setDisableReset] = useState<boolean>(true);
  const [disableStart, setDisableStart] = useState<boolean>(false);

  // Return cleanup function to clear any running intervals
  // on the event of component unmount
  useEffect(() => {
    return () => clearInterval(intervalRef.current);
  }, []);

  const calculateTime = () => {
    setCurrentTime(Date.now());
  };

  const startTimer = () => {
    setDisableStart(true);
    setDisableStop(false);

    // Only update start time if reset to 0
    if (!startTime) {
      setStartTime(Date.now());
    }

    // Invoke once immediately
    calculateTime();

    // Instantiate interval
    intervalRef.current = setInterval(() => {
      calculateTime();
    }, 1);
  };

  const stopTimer = () => { ... };

  const resetTimer = () => { ... };

  // Compute the minutes, seconds, and milliseconds from time delta
  const delta: number = currentTime - startTime; // in ms
  const minutes: string = Math.floor(delta / (1000 * 60)).toString();
  const seconds: string = (Math.floor(delta / 1000) % 60)
    .toString()
    .padStart(2, "0");
  const milliseconds: string = (delta % 1000).toString().padStart(3, "0");

  return (
    <React.Fragment>
      <div className="container">
        <h1>Stop Watch</h1>
      </div>
      <Layout seconds={seconds} minutes={minutes} milliseconds={milliseconds} />
      <Buttons ... />
    </React.Fragment>
  );
};

Edit usestate-doesnt-work-first-time-when-given-date-in-string-while-implementing-st#70617216

Upvotes: 1

Related Questions