Next.js+Redux Toolkit中使用localStorage.getItem报错的解决方案咨询
问题描述
在Redux Toolkit的slice中调用localStorage.setItem()可正常运行,但调用localStorage.getItem()时提示ReferenceError: localStorage is not defined错误。相关代码如下:
import { createSlice } from "@reduxjs/toolkit"; const users=localStorage.getItem('users')!==null ?JSON.parse(localStorage.getItem("users")):[]; const initialState = { value: users }; const Users = createSlice({ name: "users", initialState, reducers: { addUser: (state, action) => { state.value.push(action.payload); localStorage.setItem("users",JSON.stringify(state.value.map(item=>item))) },}, }); export const { addUser} = Users.actions; export default Users.reducer;
解决方案
问题原因
代码在模块顶层直接调用localStorage.getItem(),如果你的项目是服务端渲染(如Next.js、Nuxt.js)环境,服务端不存在localStorage对象,初始化slice时就会触发报错;而addUser reducer中的setItem是在客户端触发action时执行,此时已经处于浏览器环境,所以不会有问题。
解决方法1:将初始化逻辑移至客户端执行
修改slice,先将初始状态设为空数组,再在客户端组件中获取localStorage数据并dispatch初始化action:
- 更新slice代码:
import { createSlice } from "@reduxjs/toolkit"; const initialState = { value: [] }; const Users = createSlice({ name: "users", initialState, reducers: { addUser: (state, action) => { state.value.push(action.payload); localStorage.setItem("users", JSON.stringify(state.value)); }, // 添加初始化用户列表的action initUsers: (state, action) => { state.value = action.payload; } }, }); export const { addUser, initUsers } = Users.actions; export default Users.reducer;
- 在客户端根组件(如
App.js)中执行初始化:
import { useEffect } from 'react'; import { useDispatch } from 'react-redux'; import { initUsers } from './path/to/usersSlice'; function App() { const dispatch = useDispatch(); useEffect(() => { const savedUsers = localStorage.getItem('users'); if (savedUsers) { dispatch(initUsers(JSON.parse(savedUsers))); } }, [dispatch]); // 其他组件内容 } export default App;
解决方法2:在模块顶层添加环境判断
通过判断是否为客户端环境,仅在浏览器中调用localStorage:
import { createSlice } from "@reduxjs/toolkit"; // 仅在客户端环境下读取localStorage const isClient = typeof window !== 'undefined'; const users = isClient ? (localStorage.getItem('users') !== null ? JSON.parse(localStorage.getItem("users")) : []) : []; const initialState = { value: users }; const Users = createSlice({ name: "users", initialState, reducers: { addUser: (state, action) => { state.value.push(action.payload); localStorage.setItem("users", JSON.stringify(state.value)); }, }, }); export const { addUser} = Users.actions; export default Users.reducer;
内容的提问来源于stack exchange,提问作者Kawan Idris
相关产品推荐
相关产品推荐

