You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

useState未更新组件属性:react-countdown-circle-timer重置倒计时失效问题

问题原因

  • 重置逻辑错误:你在resetHandler中执行setTotalDuration(totalDuration)属于给state赋完全相同的值,React会跳过本次状态更新,不会触发组件重渲染。你给倒计时组件绑定的key属性值没有变化,组件不会重新初始化,自然不会重置计时。
  • useEffect依赖不合理:当前useEffect监听整个props对象,任意props属性变化都会触发时长重新计算,性能开销大,实际只需要监听你用到的props.item.red即可。
  • 缺少稳定的初始时长存储:你没有单独存储初始的倒计时总时长,运行过程中如果totalDuration被修改,无法直接回到初始值。

解决方案

步骤1:新增两个状态

分别存储初始倒计时时长、倒计时组件的重置标识:

// 存储初始倒计时总时长
const [initialDuration, setInitialDuration] = useState(0);
// 倒计时组件重置key,每次更新都会触发组件重新挂载
const [resetKey, setResetKey] = useState(0);

步骤2:修正useEffect逻辑与依赖

useEffect(() => {
  const myDuration =
    parseInt(props.item.red.split(":")[0]) * 60 +
    parseInt(props.item.red.split(":")[1]) +
    30;
  // 同时更新初始时长和当前运行时长
  setInitialDuration(myDuration);
  setTotalDuration(myDuration);
// 只监听用到的props属性
}, [props.item.red]);

步骤3:修正重置逻辑

每次点击重置按钮时更新重置key,触发倒计时组件重新挂载,自动回到初始时长:

const resetHandler = () => {
  setTimerOn(false);
  // 更新重置key,触发倒计时组件重新初始化
  setResetKey(prev => prev + 1);
};

如果你需要点击暂停(停止)按钮时同时重置,只需要把上面的重置key更新逻辑加到stopHandler里即可。

步骤4:修改倒计时组件的key属性

<CountdownCircleTimer
  // 绑定重置key
  key={resetKey}
  isPlaying={timerOn}
  duration={initialDuration}
  // 其余属性保持不变
  ...
>

完整修改后代码

import { Card, Col, Row } from "react-bootstrap";
import { CountdownCircleTimer } from "react-countdown-circle-timer";
import { useEffect, useState } from "react";
// 注意:代码中用到的classes需要确保你已经正确引入了样式文件,比如import classes from './xxx.module.css'

const formatRemainingTime = (time) => {
  const minutes = Math.floor((time % 3600) / 60);
  let seconds = time % 60;
  if (seconds < 10 && seconds > -1) {
    seconds = `0${seconds}`;
  }
  return `${minutes}:${seconds}`;
};

const renderTime = ({ remainingTime }) => {
  return (
    <div className={classes.timer}>
      <div className={classes.text}>Remaining</div>
      <div className={classes.value}>{formatRemainingTime(remainingTime)}</div>
      <div className={classes.text}></div>
    </div>
  );
};

function MainItem(props) {
  const [totalDuration, setTotalDuration] = useState(0);
  const [timerOn, setTimerOn] = useState(false);
  // 新增状态
  const [initialDuration, setInitialDuration] = useState(0);
  const [resetKey, setResetKey] = useState(0);

  useEffect(() => {
    const myDuration =
      parseInt(props.item.red.split(":")[0]) * 60 +
      parseInt(props.item.red.split(":")[1]) +
      30;
    setInitialDuration(myDuration);
    setTotalDuration(myDuration);
  }, [props.item.red]);

  const startHandler = () => {
    setTimerOn(true);
  };
  const stopHandler = () => {
    setTimerOn(false);
    // 如果需要点击停止就重置,放开下面一行注释
    // setResetKey(prev => prev + 1);
  };

  const resetHandler = () => {
    setTimerOn(false);
    setResetKey(prev => prev + 1);
  };

  return (
    <Row>
      <Col>
        <Card>
          <Card.Body>
            <Row>
              <Col>
                <div>
                  <button onClick={startHandler}>启动</button>
                  <button onClick={stopHandler}>暂停</button>
                  <button onClick={resetHandler}>重置</button>
                </div>
              </Col>
              <Col className={classes.timer_wrapper}>
                <CountdownCircleTimer
                  key={resetKey}
                  isPlaying={timerOn}
                  duration={initialDuration}
                  size={300}
                  strokeWidth={20}
                  trailColor={"#363537"}
                  colors={[
                    ["#42b0f5", 0.5],
                    ["#42b0f5", 0.01],
                    ["#2bb32b", 0.2],
                    ["#2bb32b", 0.01],
                    ["#eeee60", 0.2],
                    ["#eeee60", 0.01],
                    ["#ff4a2e"],
                  ]}
                  onComplete={() => [true, 1000]}
                >
                  {renderTime}
                </CountdownCircleTimer>
              </Col>
            </Row>
          </Card.Body>
        </Card>
      </Col>
    </Row>
  );
}
export default MainItem;

内容的提问来源于stack exchange,提问作者user2484249

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.28 07:24:06