Next.js应用服务端与客户端Redux Store不同步致客户端崩溃排查
Next.js + Redux 客户端导航后Store对象为空导致崩溃的解决方案
问题根源
- 组件未处理数据未加载状态:
Data组件直接调用parseISO(post?.createdAt),当post为undefined(客户端HYDRATE完成前或数据加载失败时),parseISO接收空值会抛出错误,引发崩溃。 - HYDRATE逻辑与初始化存在隐患:若
initialState未明确初始化,或HYDRATE合并逻辑不符合预期,会导致客户端无法正确同步服务端Store状态。
具体修复步骤
1. 组件层面增加空值校验
修改Data组件,先判断数据是否存在再执行格式化逻辑,避免空值调用:
function Data() { const {post} = useAppSelector(({post}) => post) // 数据未加载时返回占位内容 if (!post) { return <div>加载中...</div>; } const parsed = parseISO(post.createdAt) const date = format(parsed, 'dd MMMM yyyy, HH:MM', {locale: enGB}) return ( // 原页面渲染内容 ); } export default Data;
2. 优化postSlice的状态初始化与HYDRATE逻辑
明确初始化状态,并完善HYDRATE的合并规则,确保服务端状态能正确同步到客户端:
// 补充定义你的实际类型,比如PublicPost interface PostState { post: PublicPost | null; } const initialState: PostState = { post: null, }; export const postSlice = createSlice({ name: 'post', initialState, reducers: { setPost: (state, action) => { state.post = action.payload }, // 可选:页面卸载时清空状态,避免残留旧数据 clearPost: (state) => { state.post = null } }, extraReducers: { [HYDRATE]: (state, action) => { // 优先使用服务端返回的post数据 if (action.payload.post.post) { return { ...state, ...action.payload.post, }; } // 服务端无数据时保留客户端现有状态 return state; }, }, }); export const { setPost, clearPost } = postSlice.actions; export default postSlice.reducer;
3. 可选:页面卸载时重置状态
在post/[id]页面添加卸载钩子,切换页面时清空post状态,避免旧数据干扰后续页面:
import { useEffect } from 'react'; import { useDispatch } from 'react-redux'; import { clearPost } from '../reducers/postSlice'; function Post() { const dispatch = useDispatch(); useEffect(() => { return () => { dispatch(clearPost()); }; }, [dispatch]); return ( // 页面内容,包含Data组件 ); }
额外检查点
- 确认
next-redux-wrapper版本与Next.js版本兼容,建议使用最新稳定版。 - 检查
_app.tsx中wrapper.useWrappedStore的调用是否正确,确保Redux Provider完整包裹应用。 - 验证
getServerSideProps中data.publicPost的结构与setPost接收的payload结构一致,避免因结构不匹配导致状态设置失败。
内容的提问来源于stack exchange,提问作者Dmitri Antyfeev
相关产品推荐
相关产品推荐

