使用useEffect存储应用打开时间至数组时的异常问题
问题分析与解决方案
核心问题原因
- 直接修改状态数组导致状态不同步:你在
curStreakUpdate和checkNearliestOpenDate里直接通过this.currentStreak.push()或this.currentStreak = []修改数组,这属于可变操作,React无法追踪到状态变化,会导致组件状态与实际数据不一致,后续操作时出现数组被意外清空的情况。 - 未清理
AppState事件监听:useEffect中添加了事件监听但没有清理逻辑,当依赖项变化时会重复绑定监听,多次触发curStreakUpdate,打乱了连续登录天数的计算逻辑。 - 固定
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
相关产品推荐
相关产品推荐

