如何实现无需刷新页面自动更新下一个礼拜时间显示?
自动更新下一个礼拜时间的实现方案
问题背景
需要实现当当前时间超过已显示的礼拜时间时,自动切换到下一个_jammah礼拜时间,无需手动刷新页面。此前尝试用useState触发重渲染时出现无限循环,仅能在页面刷新时更新显示内容。
重构思路
- 禁止在渲染逻辑中直接调用状态更新函数,避免触发无限重渲染
- 用
useEffect结合定时器,计算当前时间到下一个礼拜时间的间隔,时间到后自动更新状态 - 提前提取并排序所有
_jammah时间,简化后续查找逻辑
完整代码示例
import { useState, useEffect } from 'react'; import dayjs from 'dayjs'; const timetable = { "fajr_begins": "5:54", "fajr_jammah": "6:14", "zuhr_begins": "12:51", "zuhr_jammah": "13:30", "asr_begins": "15:28", "asr_jammah": "14:10", "maghrib_begins": "18:04", "maghrib_jammah": "19:49", "isha_begins": "19:27", "isha_jammah": "20:00" }; export default function PrayerTime() { const [nextPrayer, setNextPrayer] = useState(null); // 提取并排序所有jammah时间 const getSortedJammahTimes = () => { return Object.entries(timetable) .filter(([key]) => key.endsWith("_jammah")) .map(([name, timeStr]) => ({ name, time: dayjs(timeStr, 'hh:mm'), timeStr })) .sort((a, b) => a.time.diff(b.time)); }; // 查找当前下一个礼拜时间 const findNextPrayer = () => { const now = dayjs(); const sortedTimes = getSortedJammahTimes(); // 优先找当天未到的时间 let next = sortedTimes.find(prayer => prayer.time.isAfter(now)); // 当天所有时间已过时,自动切换到次日第一个礼拜时间 if (!next) { next = { ...sortedTimes[0], time: sortedTimes[0].time.add(1, 'day') }; } return next; }; // 初始化+自动更新下一个礼拜时间 useEffect(() => { const updateNextPrayer = () => { const prayer = findNextPrayer(); setNextPrayer(prayer); // 计算剩余时间,设置定时器触发下一次更新 const timeUntilNext = prayer.time.diff(dayjs()); const timer = setTimeout(updateNextPrayer, timeUntilNext); return () => clearTimeout(timer); }; const cleanup = updateNextPrayer(); return cleanup; }, []); if (!nextPrayer) return <div>加载中...</div>; return ( <div> <h3>下一个礼拜:{nextPrayer.name.replace('_jammah', '')}</h3> <p>时间:{nextPrayer.timeStr}</p> <p>剩余时间:{nextPrayer.time.fromNow()}</p> </div> ); }
关键说明
- 预处理排序:提前提取所有
_jammah时间并排序,避免每次遍历整个对象,提升查找效率 - 定时器驱动更新:每次找到下一个礼拜时间后,计算剩余间隔并设置定时器,时间到后自动触发状态更新,彻底避免无限循环
- 跨天处理:当天所有礼拜时间已过时,自动切换到次日第一个礼拜时间
- 内存泄漏防护:组件卸载时自动清除定时器,避免内存泄漏
内容的提问来源于stack exchange,提问作者Contradicted
相关产品推荐
相关产品推荐

