React Native中使用Moment.js设置全局初始日期的问题
问题原因
你当前的代码里,serverMoment.valueOf()是一个固定的时间戳数值,每次调用moment.now()都会直接返回这个固定值,自然不会随时间递增。
解决方案
要让模拟的基准时间能正常“流逝”,需要记录设置基准时间时的真实时间戳,每次调用moment.now()时,计算当前真实时间与设置时刻的差值,加到基准时间戳上,这样就能让模拟时间跟着真实时间同步走。
代码修改示例
基础实现(全局变量版)
import moment from 'moment'; // 全局存储基准时间戳和设置时的真实时间戳 let baseTimeStamp: number | null = null; let realSetTime: number | null = null; export const setDefaultTime = (date: string, time: string) => { const serverDate = `${date} ${time}`; const baseMoment = moment.utc(serverDate); // 保存基准时间戳,以及设置该基准时的真实时间 baseTimeStamp = baseMoment.valueOf(); realSetTime = Date.now(); // 重写moment.now,返回动态计算的时间 moment.now = function () { // 未设置基准时, fallback 到真实时间 if (!baseTimeStamp || !realSetTime) return Date.now(); // 计算真实时间流逝的差值,加到基准时间上 const elapsedTime = Date.now() - realSetTime; return baseTimeStamp + elapsedTime; }; };
React Native 状态同步版(解决全局更新后组件同步问题)
如果需要在基准时间更新后,让所有依赖该时间的组件自动重新渲染,可以结合React Context实现:
import { createContext, useContext, useState, ReactNode } from 'react'; import moment from 'moment'; const TimeContext = createContext<{ setDefaultTime: (date: string, time: string) => void; }>({ setDefaultTime: () => {} }); let baseTimeStamp: number | null = null; let realSetTime: number | null = null; export const TimeProvider = ({ children }: { children: ReactNode }) => { // 用空对象触发强制更新 const [, forceUpdate] = useState({}); const setDefaultTime = (date: string, time: string) => { const serverDate = `${date} ${time}`; const baseMoment = moment.utc(serverDate); baseTimeStamp = baseMoment.valueOf(); realSetTime = Date.now(); moment.now = function () { if (!baseTimeStamp || !realSetTime) return Date.now(); const elapsedTime = Date.now() - realSetTime; return baseTimeStamp + elapsedTime; }; // 通知所有订阅的组件重新渲染 forceUpdate({}); }; return ( <TimeContext.Provider value={{ setDefaultTime }}> {children} </TimeContext.Provider> ); }; // 自定义hook,供组件调用 export const useTime = () => useContext(TimeContext);
原理说明
- 当你调用
setDefaultTime时,会同时记录两个关键值:模拟的基准时间戳和设置该基准时的真实系统时间戳。 - 每次调用
moment.now()时,都会计算从设置基准到现在的真实时间差,把这个差值加到基准时间戳上,返回的就是“正在流逝”的模拟时间。 - 结合React Context的版本,在更新基准时间时通过
forceUpdate触发组件重渲染,确保所有依赖moment时间的组件能获取到最新的模拟时间。
内容的提问来源于stack exchange,提问作者Cemil CANLI
相关产品推荐
相关产品推荐

