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

使用useEffect存储应用打开时间至数组时的异常问题

问题分析与解决方案

核心问题原因

  1. 直接修改状态数组导致状态不同步:你在curStreakUpdate和checkNearliestOpenDate里直接通过this.currentStreak.push()或this.currentStreak = []修改数组,这属于可变操作,React无法追踪到状态变化,会导致组件状态与实际数据不一致,后续操作时出现数组被意外清空的情况。
  2. 未清理AppState事件监听:useEffect中添加了事件监听但没有清理逻辑,当依赖项变化时会重复绑定监听,多次触发curStreakUpdate,打乱了连续登录天数的计算逻辑。
  3. 固定dt值与依赖项设置矛盾:代码中dt是固定的2022-09-14,但实际需要动态获取当前日期,同时依赖项设置不合理导致逻辑触发时机错误。

解决方案步骤

1. 改用不可变方式更新状态

在类组件中,必须通过setState更新状态,不能直接修改this.state中的数组:

curStreakUpdate = (date: string) => {
  this.setState(prevState => {
    const currentStreak = [...prevState.currentStreak];
    const nearliestDateOpen = currentStreak[currentStreak.length - 1];
    const dateNear: any = new Date(nearliestDateOpen);
    const dateNow: any = new Date(date);

    if (currentStreak.length === 0) {
      currentStreak.push(date);
      return {
        currentStreak,
        longestStreak: currentStreak.length,
        totalPrays: prevState.totalPrays + 1
      };
    } else {
      if (dateNow - dateNear !== 0) {
        if (dateNow - dateNear === 86400000) {
          if (!currentStreak.includes(date)) {
            currentStreak.push(date);
            return {
              currentStreak,
              longestStreak: currentStreak.length,
              totalPrays: prevState.totalPrays + 1
            };
          }
        } else {
          return {
            currentStreak: [],
            totalPrays: prevState.totalPrays + 1
          };
        }
      }
      // 日期相同的情况,不修改连续天数,只更新总次数
      return {
        totalPrays: prevState.totalPrays + 1
      };
    }
  }, () => {
    console.log(this.state.currentStreak); // 状态更新完成后再打印
  });
};

注:把原来的checkNearliestOpenDate逻辑整合到setState的回调中,确保所有状态更新都是不可变操作,React能正确追踪状态变化。

2. 修复useEffect的事件监听与依赖项

动态获取当前日期,并添加清理函数移除监听,同时正确设置依赖项:

const { curStreakUpdate } = useStore().streakStore;

// 动态获取当前日期
const getCurrentDate = () => new Date().toISOString().split('T')[0];

useEffect(() => {
  const handleAppStateChange = (state: string) => {
    if (state === 'active') {
      const currentDate = getCurrentDate();
      curStreakUpdate(currentDate);
    }
  };

  AppState.addEventListener('change', handleAppStateChange);

  // 组件卸载或依赖变化时移除监听,避免重复触发
  return () => {
    AppState.removeEventListener('change', handleAppStateChange);
  };
}, [curStreakUpdate]); // 依赖curStreakUpdate,确保回调始终引用最新的方法

3. 验证逻辑正确性

修改后,每次应用激活时会传入当前日期,状态更新通过setState完成,React能正确维护currentStreak的状态,不会出现意外清空的情况。同时,事件监听会在组件卸载时自动清理,避免重复触发逻辑。

预期输出示例

连续两天打开应用时,控制台输出应符合预期:

Array [
  "2022-09-15",
]
Array [
  "2022-09-15",
  "2022-09-16",
]

内容的提问来源于stack exchange,提问作者Nguyễn Hiếu

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 17:10:25