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

React实现25+5时钟页面无显示 求错误排查帮助

React 25+5时钟页面空白问题修复

问题说明

我用React开发的25+5时钟原本可正常运行,但当前页面无任何内容显示,无法定位错误位置。多次参考教程视频,并使用ChatGPT及多款在线JS校验工具排查,仍未找到问题。

原代码

JSX代码

class App extends React.Component {
  constructor(props) {
    super(props);
    this.loop = undefined;
    this.state = {
      breakCount: 5,
      sessionCount: 25,
      clockCount: 25 * 60,
      currentTimer: "Session",
      isPlaying: false,
      loop: undefined
    }
  }
  
 handlePlayPause() {
   const {isPlaying} = this.state;
   
   if (isPlaying){
      clearInterval(this.loop);
   } else {
     this.loop = setInterval(() => {}, 1000);
   }
 }

  componentWillUnmount() {
  clearInterval(this.loop);
  }
  
  convertToTime(count) {
    const minutes = Math.floor(count / 60);
    let seconds = count % 60;
    
    seconds = seconds < 10 ? ('0'+seconds) : seconds;
    
    return `${minutes}:${seconds}`;
  }
  
  render() {
    const {
      breakCount, 
      sessionCount, 
      clockCount, 
      currentTimer
    } = this.state;
     
    const breakProps = {
      title: 'Break Length',
      count: breakCount,
      handleDecrease: this.handleBreakDecrease,
      handleIncrease: this.handleBreakIncrease,
    };
    
    const sessionProps = {
      title: 'Session Length',
      count: sessionCount,
      handleDecrease: this.handleSessionDecrease,
      handleIncrease: this.handleSessionIncrease,
    };
    
    return (
  &lt;div&gt;
    &lt;div className=&quot;flex&quot;&gt;
      &lt;SetTimer {...breakProps} /&gt;
      &lt;SetTimer {...sessionProps} /&gt;
    &lt;/div&gt;

    &lt;div className=&quot;clock-container&quot;&gt;
      &lt;h1&gt;{currentTimer}&lt;/h1&gt;
      &lt;span&gt;{this.convertToTime(clockCount)}&lt;/span&gt;
      &lt;div className=&quot;flex&quot;&gt;
        &lt;button onClick={this.handlePlayPause}&gt;
          &lt;i className={`fas fa-${isPlaying ? 'pause' : 'play'}`} /&gt;
        &lt;/button&gt;
        &lt;button onClick={this.handleReset}&gt;
          &lt;i className=&quot;fas fa-sync&quot; /&gt;
        &lt;/button&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
  );
}
  
const SetTimer = (props) =&gt; (
  &lt;div className=&quot;timer-container&quot;&gt;
    &lt;h1&gt;{props.title}&lt;/h1&gt;
    
      &lt;div className=&quot;flex actions-wrapper&quot;&gt;
      &lt;button onClick={props.handleDecrease}&gt;
        &lt;i className=&quot;fas fa-minus&quot; /&gt;            
        &lt;/button&gt;
      &lt;span&gt;{props.count}&lt;/span&gt;
      &lt;button onClick={props.handleIncrease}&gt;
        &lt;i className=&quot;fas fa-plus&quot; /&gt; 
      &lt;/button&gt;
      
     &lt;/div&gt;
&lt;/div&gt;)

ReactDOM.render(&lt;App/&gt;, document.getElementById('app'));

CSS代码

@import url('https://fonts.googleapis.com/css2?family=Rubik&amp;display=swap');

*{
  box-size: border-box;
}

body{
  
  background-color: #006266;
  color: white;
  font-family: 'Rubik', sans-serif;
  display:flex;
  min-height: 100vh;
  align-items: center;
  justify-content:center;
  text-align: center;
}

.flex {
  display: flex;
  align-items: center;
  justify-content: center;
  margin: 10px;
}

.timer-container {
  margin: 20px ;
}
.timer-container h2{
  margin: 0;
}

.actions-wrapper button {
  cursor: pointer;
  background-color:transparent;
  padding: 15px;
  margin: 20px;
  color: white;
  font-size: 20px;
}

.actions-wrapper span {
  font-size: 40px;
  margin: 0 10px;
}

.clock-container {
  display: inline-block;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  margin: 0 auto;
  border: 10px solid #fff;
  border-radius: 30px ;
  padding: 10px 50px;
}

.clock-container span{
  font-size: 50px;
}

.clock-container h1{
  margin: 0;
}

.clock-container button{
  cursor: pointer;
  background-color:transparent;
  padding: 15px;
  margin: 20px;
  color: white;
  font-size: 20px;
}

错误排查与修复

页面空白的核心原因是代码存在多个语法/逻辑错误,导致React无法正常渲染,以下是具体问题和修复方案:

  1. 事件处理函数未绑定this

    • 问题:handlePlayPause等函数调用时this指向undefined,引发报错中断渲染。
    • 修复:在constructor中绑定this,或使用箭头函数定义方法。
  2. 未定义增减和重置函数

    • 问题:代码引用了handleBreakDecrease、handleBreakIncrease等函数,但未实现这些逻辑。
    • 修复:补充实现这些函数,处理状态更新逻辑。
  3. render中引用未解构的state变量

    • 问题:render里使用isPlaying但未从this.state解构,导致变量未定义。
    • 修复:在render的解构语句中添加isPlaying。
  4. JSX转义字符错误

    • 问题:代码中的&lt;、&quot;是HTML转义字符,React无法解析,需替换为正常的<、"。
  5. CSS属性拼写错误

    • 问题:box-size: border-box;应为box-sizing: border-box;,属性名拼写错误导致样式失效。

修正后的完整代码

JSX代码

class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      breakCount: 5,
      sessionCount: 25,
      clockCount: 25 * 60,
      currentTimer: "Session",
      isPlaying: false,
    };
    // 绑定this指向
    this.handlePlayPause = this.handlePlayPause.bind(this);
    this.handleBreakDecrease = this.handleBreakDecrease.bind(this);
    this.handleBreakIncrease = this.handleBreakIncrease.bind(this);
    this.handleSessionDecrease = this.handleSessionDecrease.bind(this);
    this.handleSessionIncrease = this.handleSessionIncrease.bind(this);
    this.handleReset = this.handleReset.bind(this);
    this.loop = undefined;
  }

  handlePlayPause() {
    const { isPlaying, clockCount, currentTimer } = this.state;

    if (isPlaying) {
      clearInterval(this.loop);
    } else {
      this.loop = setInterval(() => {
        this.setState(prevState => {
          if (prevState.clockCount === 0) {
            // 切换计时器类型
            const newTimer = prevState.currentTimer === "Session" ? "Break" : "Session";
            const newCount = newTimer === "Session" ? prevState.sessionCount * 60 : prevState.breakCount * 60;
            return {
              currentTimer: newTimer,
              clockCount: newCount
            };
          }
          return { clockCount: prevState.clockCount - 1 };
        });
      }, 1000);
    }
    this.setState(prevState => ({ isPlaying: !prevState.isPlaying }));
  }

  handleBreakDecrease() {
    this.setState(prevState => {
      if (prevState.breakCount > 1 && !prevState.isPlaying) {
        return { breakCount: prevState.breakCount - 1 };
      }
      return {};
    });
  }

  handleBreakIncrease() {
    this.setState(prevState => {
      if (prevState.breakCount < 60 && !prevState.isPlaying) {
        return { breakCount: prevState.breakCount + 1 };
      }
      return {};
    });
  }

  handleSessionDecrease() {
    this.setState(prevState => {
      if (prevState.sessionCount > 1 && !prevState.isPlaying) {
        return { 
          sessionCount: prevState.sessionCount - 1,
          clockCount: (prevState.sessionCount - 1) * 60
        };
      }
      return {};
    });
  }

  handleSessionIncrease() {
    this.setState(prevState => {
      if (prevState.sessionCount < 60 && !prevState.isPlaying) {
        return { 
          sessionCount: prevState.sessionCount + 1,
          clockCount: (prevState.sessionCount + 1) * 60
        };
      }
      return {};
    });
  }

  handleReset() {
    clearInterval(this.loop);
    this.setState({
      breakCount: 5,
      sessionCount: 25,
      clockCount: 25 * 60,
      currentTimer: "Session",
      isPlaying: false,
    });
  }

  componentWillUnmount() {
    clearInterval(this.loop);
  }

  convertToTime(count) {
    const minutes = Math.floor(count / 60);
    let seconds = count % 60;
    seconds = seconds < 10 ? `0${seconds}` : seconds;
    return `${minutes}:${seconds}`;
  }

  render() {
    const {
      breakCount,
      sessionCount,
      clockCount,
      currentTimer,
      isPlaying // 补上解构
    } = this.state;

    const breakProps = {
      title: 'Break Length',
      count: breakCount,
      handleDecrease: this.handleBreakDecrease,
      handleIncrease: this.handleBreakIncrease,
    };

    const sessionProps = {
      title: 'Session Length',
      count: sessionCount,
      handleDecrease: this.handleSessionDecrease,
      handleIncrease: this.handleSessionIncrease,
    };

    return (
      <div>
        <div className="flex">
          <SetTimer {...breakProps} />
          <SetTimer {...sessionProps} />
        </div>

        <div className="clock-container">
          <h1>{currentTimer}</h1>
          <span>{this.convertToTime(clockCount)}</span>
          <div className="flex">
            <button onClick={this.handlePlayPause}>
              <i className={`fas fa-${isPlaying ? 'pause' : 'play'}`} />
            </button>
            <button onClick={this.handleReset}>
              <i className="fas fa-sync" />
            </button>
          </div>
        </div>
      </div>
    );
  }
}

const SetTimer = (props) => (
  <div className="timer-container">
    <h1>{props.title}</h1>
    <div className="flex actions-wrapper">
      <button onClick={props.handleDecrease}>
        <i className="fas fa-minus" />            
      </button>
      <span>{props.count}</span>
      <button onClick={props.handleIncrease}>
        <i className="fas fa-plus" /> 
      </button>
    </div>
  </div>
);

ReactDOM.render(<App/>, document.getElementById('app'));

CSS代码

@import url('https://fonts.googleapis.com/css2?family=Rubik&display=swap');

*{
  box-sizing: border-box; /* 修正属性名 */
}

body{
  background-color: #006266;
  color: white;
  font-family: 'Rubik', sans-serif;
  display:flex;
  min-height: 100vh;
  align-items: center;
  justify-content:center;
  text-align: center;
}

.flex {
  display: flex;
  align-items: center;
  justify-content: center;
  margin: 10px;
}

.timer-container {
  margin: 20px ;
}
.timer-container h1{ /* 原代码用h2但组件里是h1,统一 */
  margin: 0;
}

.actions-wrapper button {
  cursor: pointer;
  background-color:transparent;
  padding: 15px;
  margin: 20px;
  color: white;
  font-size: 20px;
}

.actions-wrapper span {
  font-size: 40px;
  margin: 0 10px;
}

.clock-container {
  display: inline-block;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  margin: 0 auto;
  border: 10px solid #fff;
  border-radius: 30px ;
  padding: 10px 50px;
}

.clock-container span{
  font-size: 50px;
}

.clock-container h1{
  margin: 0;
}

.clock-container button{
  cursor: pointer;
  background-color:transparent;
  padding: 15px;
  margin: 20px;
  color: white;
  font-size: 20px;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 09:37:34