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

ReactJS中计算时间差时获取到undefined值的问题求助

解决输入时间间隔计算返回undefined的问题

咱们先来拆解下你遇到的核心问题:

  • 计算StartTime和EndTime的差值时总是得到undefined
  • 依赖this.state.Time的后续逻辑也因此失效

问题根源分析

1. React setState的异步特性

你在overallTime里调用setState后立刻console.log(this.state.Time),这时候state还没完成更新——React的setState是异步批量执行的,直接读取会拿到旧值或者初始的undefined。而且在onSubmit里调用overallTime后马上取this.state.Time,同样会因为异步性拿到未更新的结果。

2. 时间计算顺序与状态初始化问题

你写的this.state.StartTime - this.state.EndTime逻辑是反的(应该是结束时间减开始时间),另外如果StartTime和EndTime没有在组件初始化时赋值、或者点击文本区域时没正确设置为时间戳,它们的初始值就是undefined,相减自然也会得到undefined。


完整修复方案

我们一步步调整代码,解决这些问题:

1. 初始化时间相关状态

先在组件构造函数里把用到的状态都初始化好:

constructor(props) {
  super(props);
  this.state = {
    StartTime: null, // 初始为null,标记未开始计时
    EndTime: null,
    Time: 0,
    LettersPerSecond: 0,
    inputValue: '',
    Content: '', // 假设这是需要匹配的目标文本
    message: ''
  };
}

2. 绑定文本区域点击事件,记录开始时间

给textarea添加点击事件,只在第一次点击时记录开始时间(避免重复点击重置计时器):

handleTextareaClick = () => {
  if (!this.state.StartTime) {
    this.setState({ StartTime: Date.now() }); // 记录当前时间的毫秒数
  }
}

在render里的textarea上绑定这个事件:

<textarea 
  onClick={this.handleTextareaClick} 
  onChange={(e) => this.setState({inputValue: e.target.value})}
/>

3. 修正时间计算与状态更新逻辑

重写overallTime,利用setState的回调函数确保拿到最新状态,同时正确计算时间差(转成秒):

overallTime = () => {
  this.setState(prevState => {
    // 计算时间差(毫秒转秒),保留两位小数
    const timeDiff = (Date.now() - prevState.StartTime) / 1000;
    return {
      EndTime: Date.now(),
      Time: timeDiff.toFixed(2)
    };
  }, () => {
    // setState完成后的回调,这里能拿到更新后的Time
    console.log('输入耗时(秒):', this.state.Time);
  });
}

4. 修正提交逻辑,避免异步问题

在onSubmit里直接把时间计算和结果逻辑放在setState的回调中,确保依赖的状态都是最新的:

onSubmit = (e) => {
  e.preventDefault(); // 阻止表单默认提交行为
  const { inputValue, Content, StartTime } = this.state;

  // 先检查是否已经开始计时
  if (!StartTime) {
    this.setState({ message: '请先点击文本区域开始输入!' });
    return;
  }

  this.setState(prevState => {
    const timeDiff = (Date.now() - prevState.StartTime) / 1000;
    const inputLength = prevState.inputValue.length;
    let message = '';
    let LettersPerSecond = 0;

    if (inputValue === Content) {
      LettersPerSecond = (inputLength / timeDiff).toFixed(2);
      message = `Your score is ${LettersPerSecond} letters per second! Good job! Refresh the page for another try!`;
    } else {
      message = 'Your input is incorrect, refresh the page and start again! Remember, you always learn from your failures, so never give up!';
    }

    return {
      Time: timeDiff.toFixed(2),
      LettersPerSecond,
      message
    };
  });
}

关键知识点总结

  • React setState是异步的:不要在调用setState后立刻读取state,要用回调函数或者依赖state的生命周期方法处理更新后的逻辑。
  • 时间戳的正确使用:用Date.now()获取当前时间的毫秒数,计算后转成秒,能保证时间计算的准确性。
  • 状态初始化:所有用到的state都要初始化,避免出现undefined导致的计算错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.29 17:59:04