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

React useState动态对象赋值变NaN:时序数据求和异常求助

问题分析与修复方案

核心问题

你遇到的NaN问题主要来自两个关键点:

  1. React状态更新的异步特性:循环中多次调用setTotalHours时,闭包捕获的是旧的totalHours状态值(初始为空或未更新的旧值),而非实时更新后的状态,导致累加逻辑错误。
  2. 初始值处理与重复累加:空对象的total[key]为undefined,直接做加法会生成NaN;同时原代码最后重复处理currHourTotal,导致数值被重复累加。

修复代码(推荐方案)

重构逻辑,先一次性计算所有小时的累加总和,再批量更新状态,避免异步更新带来的闭包问题:

const [totalHours, setTotalHours] = useState<{[key: string]: number}>({});

useEffect(() => {
  if (!loading && hours.length > 0) {
    // 按小时分组,确保每个小时的统计值只保留一次
    const hourStatsMap = new Map<number, typeof hours[0]['meta']>();
    
    for (const h of hours) {
      const hour = new Date(h.timestamp).getUTCHours();
      if (h.meta) {
        hourStatsMap.set(hour, h.meta);
      }
    }

    // 计算所有状态的总累加时长(转换为小时,保留两位小数)
    const finalTotal: {[key: string]: number} = {};
    for (const meta of hourStatsMap.values()) {
      for (const key in meta) {
        const hourValue = Number((meta[key] / (1000 * 60 * 60)).toFixed(2));
        finalTotal[key] = (finalTotal[key] || 0) + hourValue;
      }
    }

    // 一次性更新状态
    setTotalHours(finalTotal);
    console.log('Total State', finalTotal);
  }
}, [loading, hours]);

若需保留循环流式更新(备选方案)

如果必须在循环中逐步更新状态,必须使用函数式更新,确保每次都基于最新的状态计算:

// 替换原循环中的setTotalHours调用部分
setTotalHours(prevState => {
  const updatedState = {...prevState};
  for (const key in h.meta) {
    const hourValue = Number((currHourTotal[key] / (1000 * 60 * 60)).toFixed(2));
    // 处理初始值,避免undefined + number生成NaN
    updatedState[key] = (updatedState[key] || 0) + hourValue;
  }
  return updatedState;
});

额外注意事项

  • 原代码中currHourTotal直接赋值会覆盖同小时的之前值,若你的hours数组中每个元素是小时内的分段统计而非小时总计,需要改为累加逻辑(currHourTotal[key] = (currHourTotal[key] || 0) + h.meta[key])。
  • 注意处理hours为空的边界情况,避免hours[0]报错。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 00:10:58