Redux createStore 弃用问题与解决方案
问题概述
在 Redux 项目中使用 createStore()
时遇到弃用警告,并且在使用 getState()
方法获取状态时返回 undefined
。虽然移除 getState()
调用后操作可以正常工作,但这显然不是理想的解决方案。
注意
Redux 官方自 2019 年起推荐使用 Redux Toolkit 来编写 Redux 代码,因为传统的 "plain Redux" 模式使用起来更加复杂。
问题分析
从提供的代码可以看出,问题出现在需要获取用户认证信息的异步操作中:
export const addProduct = product => async (dispatch, getState) => {
try {
dispatch({ type: PRODUCT_ADD_REQUEST })
const {
userLogin: { userInfo }, // 这里 getState() 返回 undefined
} = getState()
// ... 后续代码使用 userInfo.token 会出错
} catch (error) {
// 错误处理
}
}
解决方案
方案一:迁移到 Redux Toolkit(推荐)
Redux 官方推荐使用 @reduxjs/toolkit
包中的 configureStore
来替代传统的 createStore
。
安装依赖
npm install @reduxjs/toolkit
# 或者
yarn add @reduxjs/toolkit
配置 Store
import { configureStore } from '@reduxjs/toolkit'
import {
productAddReducer,
// 其他reducers...
} from './reducers/productReducers'
import {
userLoginReducer,
// 其他user reducers...
} from './reducers/userReducers'
const reducer = {
userLogin: userLoginReducer,
// 其他reducers...
}
const userInfoFromStorage = localStorage.getItem('userInfo')
? JSON.parse(localStorage.getItem('userInfo'))
: null
const preloadedState = {
userLogin: { userInfo: userInfoFromStorage },
}
const store = configureStore({
reducer,
preloadedState,
// middleware 默认已包含 Redux Thunk 和其他有用的中间件
})
export default store
创建 Slice(替代传统 Actions/Reducers)
使用 Redux Toolkit 的 createSlice
可以简化操作创建和状态管理:
import { createSlice, createAsyncThunk } from '@reduxjs/toolkit'
import axios from 'axios'
// 异步操作
export const addProduct = createAsyncThunk(
'products/addProduct',
async (product, { getState }) => {
const { userInfo } = getState().userLogin
const config = {
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${userInfo.token}`,
},
}
const { data } = await axios.post('/product', product, config)
return data
}
)
const productSlice = createSlice({
name: 'products',
initialState: {},
reducers: {},
extraReducers: (builder) => {
builder
.addCase(addProduct.pending, (state) => {
state.loading = true
})
.addCase(addProduct.fulfilled, (state, action) => {
state.loading = false
state.success = true
state.product = action.payload
})
.addCase(addProduct.rejected, (state, action) => {
state.loading = false
state.error = action.error.message
})
}
})
export default productSlice.reducer
方案二:临时兼容方案
如果你暂时不想迁移到 Redux Toolkit,可以使用兼容方式导入:
import { legacy_createStore as createStore } from 'redux'
// 或者
import { legacy_createStore } from 'redux'
const createStore = legacy_createStore
// 然后按原方式使用
const store = createStore(reducer, preloadedState, applyMiddleware(thunk))
为什么推荐使用 Redux Toolkit
优势
- 减少样板代码:自动处理常见模式
- 内置最佳实践:默认包含常用中间件(如 Redux Thunk)
- Immutable 更新逻辑:使用 Immer 库简化不可变更新
- TypeScript 支持:更好的类型推断
- 开发工具集成:与 Redux DevTools 无缝集成
解决 getState() 返回 undefined 的问题
在你的具体情况下,getState()
返回 undefined
的问题很可能是因为:
- 状态结构问题:确保你的状态结构正确
- 预加载状态格式:检查
preloadedState
的格式是否正确 - Reducer 组合:确保所有 reducer 都正确组合
使用 Redux Toolkit 的 configureStore
会自动处理许多这些问题,这也是官方推荐的原因。
迁移指南
如果你决定从传统 Redux 迁移到 Redux Toolkit,请参考以下资源:
结论
虽然 createStore
被标记为弃用,但它不会立即停止工作。然而,为了代码的长期维护性和开发体验,强烈建议迁移到 Redux Toolkit。它不仅解决了 getState()
问题,还提供了更加现代和高效的 Redux 开发方式。
重要提示
Redux Toolkit 自 2019 年起成为 Redux 的标准方式,所有新项目都应该使用它来编写 Redux 代码。