useState 在实现秒表时在字符串中给定日期时第一次不起作用

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

我已经在 https://codesandbox.io/s/blissful-lehmann-o4thw?file=/src/Layout.tsx

中上传了我的代码

我想做一个秒表。但由于钩子问题,工作不如预期。

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

我可以看到 setCurrentTime(rightNowTime) 没有更新当前时间的问题

拜托,有人建议

你让事情变得比他们需要的更复杂了。我建议只存储开始时间和当前“滴答声”,并计算这两个时间戳之间的分钟、秒和毫秒的派生“状态”。

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>
  );
};