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

React组件重渲染时如何防止日期变量被意外更新

问题根源

你的日期意外递增是两个代码逻辑问题共同导致的:

  1. addHours函数直接修改传入的Date引用类型对象:date.setTime会直接改动原对象存储的时间值,而你传入的helperDate.current是跨渲染持久存储的ref值,每次渲染执行map循环时,都会从i=1到i=6连续6次给这个ref里存的原始日期加24小时,相当于每次组件重渲染,起始日期就被往后推了6天。
  2. 渲染日期数字时直接读取helperDate.current,没有使用当前列对应偏移后的日期值,哪怕修复了累加问题,所有列也会显示同一个日期。
修复方法
  • 把日期计算改成纯函数逻辑:永远不修改传入的原始日期对象,每次计算偏移都基于原始时间戳生成新的Date实例返回,从根源避免污染ref存储的初始值。
  • 渲染每一列时,单独生成当前列对应的日期副本,用这个副本取星期和日期值,不要共用可变的ref日期对象。
  • 固定常量dayList可以提到组件作用域外,避免每次渲染重复创建。

修正后的代码

首先调整常量定义和辅助函数:

// 提到组件外的固定常量
const dayList = [
  "Sunday",
  "Monday",
  "Tuesday",
  "Wednesday",
  "Thursday",
  "Friday",
  "Saturday",
];

// 纯函数版日期偏移计算,不修改传入的原日期
const addHours = (hours, baseDate, offsetCount) => {
  const offsetTime = hours * offsetCount * 60 * 60 * 1000;
  return new Date(baseDate.getTime() + offsetTime);
};

然后修改表头渲染逻辑:

<div className="rabColumnTitlesWrapper">
  {Array(7)
    .fill(0)
    .map((_, i) => {
      // 为当前列生成独立的日期副本,不改动ref存储的初始值
      const currentColDate = addHours(24, helperDate.current, i);
      return (
        <div className="rabColumnTitle" key={i}>
          {dayList[getDay(currentColDate)]
            .substring(0, 3)
            .toUpperCase()}
          <br />
          <span>{getDate(currentColDate)}</span>
        </div>
      );
    })}
</div>

额外注意

如果你后续需要实现上一周/下一周切换功能,更新startDate状态时记得同步更新helperDate.current的值,否则切换周后表头日期不会同步刷新:

const handleWeekChange = (weekOffset) => {
  const newStartDate = addWeeks(startDate, weekOffset);
  setStartDate(newStartDate);
  setEndDate(endOfWeek(newStartDate));
  helperDate.current = newStartDate; // 同步更新ref存储的周起始日期
};

内容的提问来源于stack exchange,提问作者U. Watt

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 13:01:01