Skip to content

Redux createStore 弃用问题与解决方案

问题概述

在 Redux 项目中使用 createStore() 时遇到弃用警告,并且在使用 getState() 方法获取状态时返回 undefined。虽然移除 getState() 调用后操作可以正常工作,但这显然不是理想的解决方案。

注意

Redux 官方自 2019 年起推荐使用 Redux Toolkit 来编写 Redux 代码,因为传统的 "plain Redux" 模式使用起来更加复杂。

问题分析

从提供的代码可以看出,问题出现在需要获取用户认证信息的异步操作中:

javascript
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

安装依赖

bash
npm install @reduxjs/toolkit
# 或者
yarn add @reduxjs/toolkit

配置 Store

javascript
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 可以简化操作创建和状态管理:

javascript
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,可以使用兼容方式导入:

javascript
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 的问题很可能是因为:

  1. 状态结构问题:确保你的状态结构正确
  2. 预加载状态格式:检查 preloadedState 的格式是否正确
  3. Reducer 组合:确保所有 reducer 都正确组合

使用 Redux Toolkit 的 configureStore 会自动处理许多这些问题,这也是官方推荐的原因。

迁移指南

如果你决定从传统 Redux 迁移到 Redux Toolkit,请参考以下资源:

结论

虽然 createStore 被标记为弃用,但它不会立即停止工作。然而,为了代码的长期维护性和开发体验,强烈建议迁移到 Redux Toolkit。它不仅解决了 getState() 问题,还提供了更加现代和高效的 Redux 开发方式。

重要提示

Redux Toolkit 自 2019 年起成为 Redux 的标准方式,所有新项目都应该使用它来编写 Redux 代码。