next-redux-wrapper的HYDRATE方法页面跳转时丢失原有state如何解决?
问题1:HYDRATE action.payload为空导致状态丢失的原因和解决方法
你遇到的payload为空是因为next-redux-wrapper的HYDRATE payload是服务端运行时Redux store的完整快照,你目前在getServerSideProps里只把请求到的shopInfo、productInfo返回给了页面props,没有通过dispatch把数据写入服务端的store,所以服务端store一直停留在初始状态,自然payload是空对象。
你现在直接在HYDRATE里返回原state的临时方案,虽然能解决客户端路由跳转时的状态丢失问题,但会导致首次SSR渲染时服务端预取的store数据完全失效,页面首次加载会出现数据闪一下的问题,建议调整HYDRATE的合并逻辑,区分场景处理:
case HYDRATE: // 客户端路由跳转场景:已有客户端状态,优先保留客户端已有数据,只合并服务端新增的字段 if (typeof window !== 'undefined') { return { ...state, // 按需合并服务端返回的新数据,避免覆盖客户端已有的session、购物车等状态 shopInfo: action.payload.shopInfo ?? state.shopInfo, productInfo: action.payload.productInfo ?? state.productInfo, categories: action.payload.categories ?? state.categories } } // 首次SSR场景:客户端无现有状态,直接使用服务端预取的完整状态 return { ...action.payload }
如果需要HYDRATE payload携带你请求的数据,只要在getServerSideProps里补充dispatch逻辑即可,示例:
export const getServerSideProps = wrapper.getServerSideProps(store => async({query}) => { // 原有请求逻辑不变 let results = await Promise.all([getShopInfo(query.shopId), getProductInfo(query.productId)]) // 新增:把请求到的数据写入服务端store store.dispatch({ type: 'SET_SHOP_INFO', shopInfo: results[0] }) store.dispatch({ type: 'SET_PRODUCT_INFO', productInfo: results[1] }) return {props: { id: query.shopId, shopInfo: results[0], productInfo: results[1] }} })
问题2:刷新/地址栏跳转丢失状态的解决方案
是的,这种场景需要配合redux-persist实现状态持久化。Redux本身是内存级存储,只要页面刷新/重新加载,整个应用会重新初始化,内存里的store状态自然会被清空。redux-persist可以把你指定的状态(比如登录态session、购物车cart这类需要持久化的字段)自动存储到localStorage/sessionStorage里,应用初始化时再自动读回恢复状态。
注意适配Next.js的服务端渲染逻辑:不要在服务端执行持久化相关逻辑,避免出现window is not defined的报错,建议只在客户端环境初始化persistStore。
内容的提问来源于stack exchange,提问作者Mopparthy Ravindranath

