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

React多预订场景下useState计时器冲突问题的解决方法

解决方案:多预订独立计时器实现

核心思路

把单个状态改成按预订唯一ID存储对应倒计时的对象,同时用useEffect统一管理每个未支付预订的计时器,避免状态冲突和内存泄漏。

具体实现步骤

1. 修改状态存储结构

将单个timeOut状态改为存储多个预订倒计时的对象,key用MongoDB生成的预订唯一ID(如item._id):

const [countdowns, setCountdowns] = React.useState({});

2. 编写纯计算倒计时的工具函数

剥离状态更新逻辑,只做倒计时计算:

// 计算单个预订的剩余时间,返回格式化字符串或"已过期"
const calculateCountdown = (createdAt) => {
  const expireTime = new Date(createdAt).getTime() + 1800000; // 30分钟后过期
  const now = new Date().getTime();
  const distance = expireTime - now;

  if (distance <= 0) {
    return "已过期";
  }

  // 格式化分钟和秒为两位数字
  const min = Math.floor((distance % (1000 * 60 * 60)) / (1000 * 60)).toString().padStart(2, '0');
  const sec = Math.floor((distance % (1000 * 60)) / 1000).toString().padStart(2, '0');
  return `${min}:${sec}`;
};

3. 用useEffect统一管理计时器

遍历未支付预订,为每个预订启动独立计时器,并在组件卸载/预订列表变化时清除:

// 假设你的预订列表数据存在bookings变量中
React.useEffect(() => {
  const timers = [];

  bookings.forEach(item => {
    if (item.status === 'unPaid') {
      // 初始化当前预订的倒计时
      setCountdowns(prev => ({...prev, [item._id]: calculateCountdown(item.createdAt)}));

      // 启动每秒更新的计时器
      const timer = setInterval(() => {
        const currentCountdown = calculateCountdown(item.createdAt);
        setCountdowns(prev => ({...prev, [item._id]: currentCountdown}));

        // 过期后清除计时器,可触发数据刷新同步MongoDB状态
        if (currentCountdown === "已过期") {
          clearInterval(timer);
          // 这里可以调用刷新预订列表的API,比如fetchBookings()
        }
      }, 1000);

      timers.push(timer);
    }
  });

  // 清理函数:组件卸载或预订列表变化时清除所有计时器
  return () => timers.forEach(timer => clearInterval(timer));
}, [bookings]);

4. 渲染时获取对应预订的倒计时

直接通过预订ID从countdowns对象中取值:

<th>{item.status === 'unPaid' ? countdowns[item._id] : ''}</th>

关键注意事项

  • 必须用预订的唯一ID作为状态对象的key,确保每个预订的倒计时独立存储。
  • 用useEffect的清理函数清除计时器,避免内存泄漏和无效的状态更新。
  • 倒计时过期后建议触发数据刷新,让前端同步MongoDB中已删除的预订数据。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 09:27:29