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

ReactJS实现类似Online Stopwatch倒计时秒表及修复定时器值不更新问题

Fixing Your React Countdown Timer Issue

Hey there! Let's work through getting your countdown timer up and running properly, just like the tool you're referencing. I’ve looked over your code and found several key issues that are preventing the timer from updating when you trigger it, plus some missing pieces to make it functional.

Key Problems in Your Original Code

  • Incorrect state type: You initialized time2 as an empty string. When you try to subtract 1 from a string, you get NaN (Not a Number), so the state never updates correctly.
  • Invalid condition in componentDidUpdate: You checked for this.state.count, but count doesn’t exist in your state. You meant to check time2 instead.
  • String concatenation in toggle: Building time2 as a string means subtraction won’t work as expected—we need to handle it as a number.
  • Missing render method: There was no UI to display the countdown or trigger the timer controls!

Corrected Full Code

Here’s a revised version that fixes these issues and adds core functionality matching the countdown tool:

import React, { Component } from 'react';

export default class StopWatch extends Component {
  constructor(props) {
    super(props);
    this.state = {
      // Store time as a number, not a string
      time2: 0,
      // Track if the timer is running to prevent duplicate intervals
      isRunning: false
    };
    // Bind methods to the component instance to fix `this` context
    this.timeCount = this.timeCount.bind(this);
    this.stopTimer = this.stopTimer.bind(this);
    this.toggle = this.toggle.bind(this);
    this.resetTimer = this.resetTimer.bind(this);
  }

  timeCount() {
    // Don't start a timer if it's already running
    if (this.state.isRunning) return;

    this.setState({ isRunning: true }, () => {
      this.time = setInterval(() => {
        // Use functional state update to get the latest state value
        this.setState(prevState => {
          if (prevState.time2 <= 0) {
            this.stopTimer();
            return { time2: 0 };
          }
          return { time2: prevState.time2 - 1 };
        });
      }, 1000);
    });
  }

  stopTimer() {
    clearInterval(this.time);
    this.setState({ isRunning: false });
  }

  resetTimer() {
    this.stopTimer();
    this.setState({ time2: 0 });
  }

  componentWillUnmount() {
    // Clean up the interval when the component unmounts to avoid memory leaks
    clearInterval(this.time);
  }

  toggle(key) {
    this.setState(prevState => {
      // Convert input to a number and build the total time
      const newTime = prevState.time2 * 10 + Number(key);
      // Limit to 6 digits (max 999999 seconds = ~277 hours)
      if (newTime.toString().length > 6) return prevState;
      return { time2: newTime };
    });
  }

  // Format seconds into HH:MM:SS for display
  formatTime(seconds) {
    const hours = Math.floor(seconds / 3600);
    const minutes = Math.floor((seconds % 3600) / 60);
    const remainingSeconds = seconds % 60;
    // Pad numbers with leading zeros for a clean look
    return `${hours.toString().padStart(2, '0')}:${minutes.toString().padStart(2, '0')}:${remainingSeconds.toString().padStart(2, '0')}`;
  }

  render() {
    return (
      <div style={{ textAlign: 'center', marginTop: '50px' }}>
        {/* Display formatted countdown time */}
        <h1 style={{ fontSize: '4rem' }}>{this.formatTime(this.state.time2)}</h1>
        
        {/* Numeric input buttons */}
        <div style={{ margin: '20px 0' }}>
          {[1,2,3,4,5,6,7,8,9,0].map(num => (
            <button
              key={num}
              onClick={() => this.toggle(num)}
              disabled={this.state.isRunning}
              style={{ padding: '12px 18px', margin: '6px', fontSize: '20px', cursor: 'pointer' }}
            >
              {num}
            </button>
          ))}
        </div>

        {/* Timer control buttons */}
        <div>
          <button
            onClick={this.timeCount}
            disabled={this.state.isRunning || this.state.time2 === 0}
            style={{ 
              padding: '12px 24px', margin: '0 10px', fontSize: '18px', 
              backgroundColor: '#4CAF50', color: 'white', border: 'none', 
              borderRadius: '4px', cursor: 'pointer' 
            }}
          >
            Start
          </button>
          <button
            onClick={this.stopTimer}
            disabled={!this.state.isRunning}
            style={{ 
              padding: '12px 24px', margin: '0 10px', fontSize: '18px', 
              backgroundColor: '#f44336', color: 'white', border: 'none', 
              borderRadius: '4px', cursor: 'pointer' 
            }}
          >
            Stop
          </button>
          <button
            onClick={this.resetTimer}
            style={{ 
              padding: '12px 24px', margin: '0 10px', fontSize: '18px', 
              backgroundColor: '#2196F3', color: 'white', border: 'none', 
              borderRadius: '4px', cursor: 'pointer' 
            }}
          >
            Reset
          </button>
        </div>
      </div>
    );
  }
}

What Changed & Why

  1. State Management:

    • time2 is now a number instead of a string, so subtraction works as intended.
    • Added isRunning to track timer state, preventing duplicate intervals and disabling buttons when appropriate.
  2. Functional State Updates:

    • Used prevState in the interval to ensure we always have the latest time value, avoiding stale state issues.
  3. UI & Usability:

    • Added a formatTime method to display time in HH:MM:SS, matching the reference tool.
    • Added numeric input buttons and control buttons (Start/Stop/Reset) with disabled states for better UX.
  4. Cleanup:

    • Ensured the interval is cleared in componentWillUnmount to prevent memory leaks.

This code will let you input a number of seconds, start the countdown, stop it, reset it, and display the time correctly—just like the countdown tool you want to replicate.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 03:57:03