NextJS集成Redux Toolkit报错Cannot read property 'getState' of undefined
报错根因
抛出TypeError: Cannot read properties of undefined (reading 'getState')的直接原因是react-redux的Provider组件未接收到必填的store实例,除此之外代码中还有3处会导致后续运行异常的问题:
<Provider>标签未传入store属性,组件内部无法读取store实例上的getState方法,直接触发当前报错- userSlice中reducers定义的方法名和导出的action名不匹配:reducers里写的方法是
setTotal,导出时却解构setTotalUsers,后续调用dispatch时会拿到undefined触发报错 - useSelector取值路径错误:配置store时userReducer被挂载在
user切片下,总用户数的访问路径应为state.user.totalUsers,直接读取state.totalUser既不符合state结构,还存在变量名单复数拼写错误 - 代码存放位置不规范:store相关逻辑放在
pages目录下,会被Next.js默认解析为路由,存在不必要的路由暴露风险
修复方案
1. 给Provider传入store实例
修改pages/_app.js,补全必填的store属性,同时优化store变量命名增强语义:
import '../styles/globals.css'; import { Provider } from 'react-redux'; // 如果后续把store移到根目录,这里路径改为'../store'即可 import store from './store/index'; function MyApp({ Component, pageProps }) { return ( <Provider store={store}> <Component {...pageProps} /> </Provider> ); } export default MyApp
2. 修正userSlice的action命名不匹配问题
修改pages/store/userSlice.js,统一reducers方法名和导出的action名:
import { createSlice } from "@reduxjs/toolkit"; const initialState = { totalUsers: 0, currentUser: { "id": "", "email": "", "first_name": "", "last_name": "", "avatar": "" } } export const userSlice = createSlice({ name: 'user', initialState, reducers: { // 原方法名setTotal改为setTotalUsers,和导出名称保持一致 setTotalUsers: (state, action) => { state.totalUsers = action.payload; }, setCurrentUser: (state, action) => { state.currentUser = action.payload; }, } }) export const { setTotalUsers, setCurrentUser } = userSlice.actions; export const userReducer = userSlice.reducer;
同步修改store配置文件pages/store/index.js的变量命名:
import { configureStore } from "@reduxjs/toolkit"; import { userReducer } from './userSlice'; const store = configureStore({ reducer: { user: userReducer }, }); export default store;
3. 修正页面中useSelector的取值路径
修改pages/index.js,按照state的实际结构读取数据,补全API拉取逻辑的位置参考:
import styles from '../styles/Home.module.css'; import { useSelector, useDispatch } from 'react-redux'; import { setTotalUsers, setCurrentUser } from './store/userSlice'; import { useEffect } from 'react'; export default function Home() { // 按切片路径读取totalUsers字段 const totalUsers = useSelector((state) => state.user.totalUsers); const dispatch = useDispatch(); useEffect(() => { const fetchUserData = async () => { // 此处写入你的API拉取逻辑 // 拉取完成后调用dispatch更新store即可 // dispatch(setTotalUsers(接口返回的总用户数)) // dispatch(setCurrentUser(接口返回的当前用户数据)) } fetchUserData() }, [dispatch]) return ( <div> Total User: {totalUsers} </div> ) }
4. (推荐优化)调整store存放位置
在项目根目录新建store文件夹,将原pages/store下的index.js、userSlice.js移动到根目录的store文件夹中,避免Next.js将store逻辑解析为页面路由。移动后同步修改所有引用路径:_app.js中store的导入路径改为import store from '../store',index.js中userSlice的导入路径改为import { setTotalUsers, setCurrentUser } from '../store/userSlice'即可。
内容的提问来源于stack exchange,提问作者Karnik Kanojia
相关产品推荐
相关产品推荐

