Files
digital-pilates/docs/mood-calendar-refresh-fix.md
richarjiang 7d28b79d86 feat: 集成推送通知功能及相关组件
- 在项目中引入expo-notifications库,支持本地推送通知功能
- 实现通知权限管理,用户可选择开启或关闭通知
- 新增通知发送、定时通知和重复通知功能
- 更新个人页面,集成通知开关和权限请求逻辑
- 编写推送通知功能实现文档,详细描述功能和使用方法
- 优化心情日历页面,确保数据实时刷新
2025-08-22 22:00:05 +08:00

5.0 KiB
Raw Permalink Blame History

心情日历数据实时刷新修复方案

问题描述

用户编辑或新建心情后,当天的心情数据没有实时更新,必须退出页面或切换日期再切换回来才会生效。

问题原因

  1. 本地状态与 Redux 状态不同步:心情日历页面使用本地状态 moodRecordsselectedDateMood 来管理数据,而不是直接使用 Redux store 中的数据。

  2. 缺少页面焦点监听:当用户从编辑页面返回时,没有监听页面焦点变化来刷新数据。

  3. 数据流不一致:编辑页面通过 Redux 更新数据,但日历页面没有监听这些变化。

修复方案

1. 迁移到 Redux 状态管理

修改文件: app/mood/calendar.tsx

移除本地状态

// 移除这些本地状态
const [selectedDateMood, setSelectedDateMood] = useState<any>(null);
const [moodRecords, setMoodRecords] = useState<Record<string, any[]>>({});

使用 Redux 状态

// 使用 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

import { router, useLocalSearchParams, useFocusEffect } from 'expo-router';
import React, { useEffect, useState, useCallback } from 'react';

添加焦点监听器

// 监听页面焦点变化,当从编辑页面返回时刷新数据
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. 简化数据加载逻辑

移除手动状态更新

// 加载选中日期的心情记录
const loadDailyMoodCheckins = async (dateString: string) => {
  try {
    await fetchMoodRecords(dateString);
    // 不需要手动设置 selectedDateMood因为它现在从 Redux store 中获取
  } catch (error) {
    console.error('加载心情记录失败:', error);
  }
};

简化月份数据加载

// 加载整个月份的心情数据
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 数据渲染图标

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 (
      <View style={[styles.moodIconContainer, { backgroundColor: mood?.color }]}>
        <View style={styles.moodIcon}>
          <Text style={styles.moodEmoji}>{mood?.emoji || '😊'}</Text>
        </View>
      </View>
    );
  }

  return (
    <View style={styles.defaultMoodIcon}>
      <Text style={styles.defaultMoodEmoji}>😊</Text>
    </View>
  );
};

修复效果

修复前

  • 用户编辑心情后,日历页面数据不更新
  • 需要退出页面或切换日期才能看到变化
  • 用户体验不佳

修复后

  • 用户编辑心情后,日历页面数据立即更新
  • 页面焦点变化时自动刷新数据
  • 数据状态统一管理,避免不一致

技术要点

  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