NuxtJS store读取localStorage值返回undefined但UI可正常渲染问题
问题根源
这个不稳定现象本质是Nuxt SSR hydration机制导致的:
- 你的Vuex state初始化逻辑仅会在store实例首次创建时执行。如果页面是首次打开/刷新触发服务端渲染,服务端创建store实例时
process.browser为false,所以token、user_id都会被初始化为undefined,这个服务端生成的state会被序列化后随HTML返回给客户端。 - 客户端激活(hydrate)阶段会直接复用服务端返回的state,不会重新执行state初始化函数读取localStorage,所以此时你从store拿到的就是undefined。
- 80%概率执行成功的场景,对应你从站内其他页面客户端路由导航过来的情况:此时store已经在客户端完成初始化,能正常读取localStorage的值。
- UI能正常渲染是因为localStorage读取后大概率有后续的mutation更新了store的state,触发响应式更新UI,但这个更新时机晚于
beforeMount、mounted钩子的执行时间。
另外注意:process.browser已经被Nuxt废弃,推荐替换为process.client判断客户端环境。
解决方案
方案1:通过客户端插件初始化持久化状态(最推荐,兼容SSR场景)
- 调整store的state默认值,新增对应修改state的mutation:
// store/index.js export const state = () => ({ token: null, user_id: null, }) export const mutations = { setToken(state, token) { state.token = token }, setUserId(state, userId) { state.user_id = userId } }
- 新建客户端专属插件
plugins/init.client.js,在客户端初始化阶段读取localStorage写入store:
// plugins/init.client.js export default ({ store }) => { store.commit('setToken', localStorage.getItem('token')) store.commit('setUserId', localStorage.getItem('user_id')) }
- 在
nuxt.config.js中注册该插件:
// nuxt.config.js export default { plugins: [ '~/plugins/init.client.js' ] }
方案2:页面关闭SSR(适用不需要SSR的业务场景)
直接在当前页面组件顶部添加配置,让整个页面走客户端渲染,store初始化时就能直接读取localStorage:
export default { ssr: false, // 其他组件逻辑 }
方案3:调整组件判断逻辑时机
如果需要保留当前SSR配置,可以通过监听状态或者等待hydrate完成后再执行逻辑:
// 写法1:用watch监听登录状态,immediate保证初始化时也会触发 watch: { isLoggedIn: { handler(newVal) { if (newVal) { console.log("IS THIS CLAUSE RUNNING?"); } }, immediate: true } } // 写法2:钩子中等待nextTick完成hydrate后再判断 async beforeMount () { await this.$nextTick() if (this.isLoggedIn) { console.log("IS THIS CLAUSE RUNNING?"); } }
内容的提问来源于stack exchange,提问作者Lorza
相关产品推荐
相关产品推荐

