Remix组件调用datetime.hour/minute后渲染失败问题排查
问题:Remix组件调用DateTime的hour/minute属性导致客户端白屏
在Remix项目中,当组件调用DateTime实例的hour或minute属性时,客户端入口渲染失败,页面出现白屏。传入的时间值为'2022-08-31T08:25:00.000Z'。
初始组件实现
import React from "react"; import { DateTime } from "luxon"; type CommonProps = { time: String; }; type Props = CommonProps; export const MlTimeComponentNew: React.FC<Props> = ({ time }) => { // @ts-ignore const parsed = DateTime.fromISO(time); return ( <div className="mb-4 flex justify-center" key={12345}> <div className="ml-3 text-2xl"> {parsed.hour} </div> </div> ); };
修复后的组件实现
import React, { useEffect, useState } from "react"; import { DateTime } from "luxon"; type CommonProps = { time: String; }; type Props = CommonProps; export const MlTimeComponentNew: React.FC<Props> = ({ time }) => { const parsed2 = DateTime.fromISO(time, {zone: 'utc'}); const [hour, setHour] = useState(0); useEffect(() => { setHour(parsed2.hour); }, []); return ( <div className="mb-4 flex justify-center" key={12345}> <div className="ml-3 text-2xl"> {hour} </div> </div> ); };
问题原因解析
- 时区不一致导致同构渲染内容不匹配:Remix是同构渲染框架,服务端渲染时默认使用服务器时区,客户端则使用用户本地时区。初始代码中
DateTime.fromISO(time)未指定时区,导致服务端和客户端解析出的DateTime实例时区不同,进而hour值可能存在差异。 - Hydration校验失败终止渲染:Remix对服务端输出的HTML和客户端Hydrate生成的DOM一致性要求严格。一旦两者内容(比如显示的小时数)不匹配,React会抛出Hydration错误,直接终止客户端渲染,表现为页面白屏。
修复代码通过两个点解决问题:一是指定{zone: 'utc'}确保服务端和客户端用同一时区解析时间,从根源消除内容差异;二是用useEffect在客户端挂载后再设置小时数,绕开了服务端与客户端初始渲染的内容校验冲突。
内容的提问来源于stack exchange,提问作者user2700025
相关产品推荐
相关产品推荐

