如何解决Next.js中使用localStorage持久化Context的Hydration错误?
解决Next.js中localStorage持久化Context的Hydration错误
问题原因
Next.js的服务端渲染(SSR)机制下,服务端执行组件代码时不存在window对象,因此useState的初始值会采用默认的initialState;但客户端在Hydration阶段会从localStorage读取数据作为初始状态,导致服务端渲染的DOM内容与客户端渲染内容不匹配,触发Hydration错误。
解决方案
核心是让服务端和客户端的初始渲染状态保持一致,待客户端完成Hydration后,再从localStorage加载数据更新状态:
- 初始化
useState时直接使用默认的initialState,确保两端初始状态统一 - 利用
useEffect在客户端环境中读取localStorage并更新状态(useEffect仅在客户端执行)
修改后的完整代码
import { createContext, Dispatch, SetStateAction, useState, useEffect, ReactNode } from 'react'; type AppState = { name: string; salary: number; info: { email: string; department: string; }; }; interface Props { children: ReactNode; } const initialState: AppState = { name: "osamu1908", salary: 2000, info: { email: "dynamic@gmail.com", department: "software developer", }, }; export const AppState = createContext<AppState>(initialState); export const AppStateSet = createContext<Dispatch<SetStateAction<AppState>>>( () => {} ); const AppStateProvider = ({ children }: Props) => { // 服务端与客户端初始状态统一为默认值 const [state, setState] = useState<AppState>(initialState); // 客户端挂载后读取localStorage并更新状态 useEffect(() => { const savedState = localStorage.getItem("state"); if (savedState) { setState(JSON.parse(savedState) as AppState); } }, []); // 状态变化时同步到localStorage useEffect(() => { localStorage.setItem("state", JSON.stringify(state)); }, [state]); return ( <AppState.Provider value={state}> <AppStateSet.Provider value={setState}>{children}</AppStateSet.Provider> </AppState.Provider> ); }; export default AppStateProvider;
关键说明
- 初始
useState使用默认值,保证服务端渲染内容与客户端Hydration初始内容一致,避免不匹配问题 - 第一个
useEffect依赖项为空数组,仅在客户端组件挂载后执行一次,此时读取localStorage更新状态不会干扰Hydration流程 - 第二个
useEffect监听state变化,同步数据到localStorage,保持持久化逻辑不变
内容的提问来源于stack exchange,提问作者osamu1908
相关产品推荐
相关产品推荐

