# 心情日历数据实时刷新修复方案 ## 问题描述 用户编辑或新建心情后,当天的心情数据没有实时更新,必须退出页面或切换日期再切换回来才会生效。 ## 问题原因 1. **本地状态与 Redux 状态不同步**:心情日历页面使用本地状态 `moodRecords` 和 `selectedDateMood` 来管理数据,而不是直接使用 Redux store 中的数据。 2. **缺少页面焦点监听**:当用户从编辑页面返回时,没有监听页面焦点变化来刷新数据。 3. **数据流不一致**:编辑页面通过 Redux 更新数据,但日历页面没有监听这些变化。 ## 修复方案 ### 1. 迁移到 Redux 状态管理 **修改文件**: `app/mood/calendar.tsx` #### 移除本地状态 ```typescript // 移除这些本地状态 const [selectedDateMood, setSelectedDateMood] = useState(null); const [moodRecords, setMoodRecords] = useState>({}); ``` #### 使用 Redux 状态 ```typescript // 使用 Redux store 中的数据 const moodRecords = useAppSelector(state => state.mood.moodRecords); // 获取选中日期的数据 const selectedDateString = selectedDay ? dayjs(currentMonth).date(selectedDay).format('YYYY-MM-DD') : null; const selectedDateMood = selectedDateString ? useAppSelector(selectLatestMoodRecordByDate(selectedDateString)) : null; ``` ### 2. 添加页面焦点监听 #### 导入 useFocusEffect ```typescript import { router, useLocalSearchParams, useFocusEffect } from 'expo-router'; import React, { useEffect, useState, useCallback } from 'react'; ``` #### 添加焦点监听器 ```typescript // 监听页面焦点变化,当从编辑页面返回时刷新数据 useFocusEffect( useCallback(() => { // 当页面获得焦点时,刷新当前月份的数据和选中日期的数据 const refreshData = async () => { if (selectedDay) { const selectedDateString = dayjs(currentMonth).date(selectedDay).format('YYYY-MM-DD'); await loadDailyMoodCheckins(selectedDateString); } await loadMonthMoodData(currentMonth); }; refreshData(); }, [currentMonth, selectedDay, loadDailyMoodCheckins, loadMonthMoodData]) ); ``` ### 3. 简化数据加载逻辑 #### 移除手动状态更新 ```typescript // 加载选中日期的心情记录 const loadDailyMoodCheckins = async (dateString: string) => { try { await fetchMoodRecords(dateString); // 不需要手动设置 selectedDateMood,因为它现在从 Redux store 中获取 } catch (error) { console.error('加载心情记录失败:', error); } }; ``` #### 简化月份数据加载 ```typescript // 加载整个月份的心情数据 const loadMonthMoodData = async (targetMonth: Date) => { try { const startDate = dayjs(targetMonth).startOf('month').format('YYYY-MM-DD'); const endDate = dayjs(targetMonth).endOf('month').format('YYYY-MM-DD'); const historyData = await fetchMoodHistoryRecords({ startDate, endDate }); // 历史记录已经通过 fetchMoodHistoryRecords 自动存储到 Redux store 中 // 不需要额外的处理 } catch (error) { console.error('加载月份心情数据失败:', error); } }; ``` ### 4. 更新心情图标渲染 #### 使用 Redux 数据渲染图标 ```typescript const renderMoodIcon = (day: number | null, isSelected: boolean) => { if (!day) return null; // 检查该日期是否有心情记录 - 现在从 Redux store 中获取 const dayDateString = dayjs(currentMonth).date(day).format('YYYY-MM-DD'); const dayRecords = moodRecords[dayDateString] || []; const moodRecord = dayRecords.length > 0 ? dayRecords[0] : null; if (moodRecord) { const mood = moodOptions.find(m => m.type === moodRecord.moodType); return ( {mood?.emoji || '😊'} ); } return ( 😊 ); }; ``` ## 修复效果 ### 修复前 - 用户编辑心情后,日历页面数据不更新 - 需要退出页面或切换日期才能看到变化 - 用户体验不佳 ### 修复后 - 用户编辑心情后,日历页面数据立即更新 - 页面焦点变化时自动刷新数据 - 数据状态统一管理,避免不一致 ## 技术要点 1. **统一状态管理**:所有心情数据都通过 Redux 管理,确保数据一致性。 2. **响应式更新**:使用 `useAppSelector` 监听 Redux 状态变化,自动更新 UI。 3. **页面焦点监听**:使用 `useFocusEffect` 监听页面焦点变化,确保从其他页面返回时数据是最新的。 4. **异步数据加载**:保持异步数据加载的性能优势,同时确保数据同步。 ## 相关文件 - `app/mood/calendar.tsx` - 心情日历页面 - `app/mood/edit.tsx` - 心情编辑页面 - `store/moodSlice.ts` - 心情 Redux slice - `hooks/useMoodData.ts` - 心情数据管理 hook