Redux createStore() 已弃用 - 无法在 Redux 操作中从 getState() 获取状态

Eva*_*n B 58 javascript redux redux-toolkit

因此,createStore()Redux 现已弃用,并由@reduxjs/toolkitconfigureStore()推荐。

我很确定这与无法在我的操作中userInfo使用状态有关getState()

getState()userLogin回报undefined。但是当我删除 时getState(),该操作就起作用了。

店铺:

import { configureStore } from '@reduxjs/toolkit'
import thunk from 'redux-thunk'
import {
  productAddReducer,
  productDeleteReducer,
  productDetailsReducer,
  productListReducer,
  productUpdateReducer,
} from './reducers/productReducers'
import { composeWithDevTools } from 'redux-devtools-extension'
import {
  userLoginReducer,
  userRegisterReducer,
  userDetailsReducer,
  userListReducer,
  userDeleteReducer,
  userUpdateReducer,
} from './reducers/userReducers'

const reducer = {
  // User
  userLogin: userLoginReducer,
  userRegister: userRegisterReducer,
  userDetails: userDetailsReducer,
  userList: userListReducer,
  userDelete: userDeleteReducer,
  userUpdate: userUpdateReducer,
  // Product
  productAdd: productAddReducer,
  productList: productListReducer,
  productDetails: productDetailsReducer,
  productUpdate: productUpdateReducer,
  productDelete: productDeleteReducer,
}

const userInfoFromStorage = localStorage.getItem('userInfo')
  ? JSON.parse(localStorage.getItem('userInfo'))
  : null

const preLoadedState = {
  userLogin: { userInfo: userInfoFromStorage },
}

const middleware = [thunk]

const store = configureStore({
  reducer,
  preLoadedState,
  middleware,
})

export default store
Run Code Online (Sandbox Code Playgroud)

行动:

import axios from 'axios'
import {
  PRODUCT_ADD_FAIL,
  PRODUCT_ADD_REQUEST,
  PRODUCT_ADD_SUCCESS,
  PRODUCT_DELETE_FAIL,
  PRODUCT_DELETE_REQUEST,
  PRODUCT_DELETE_SUCCESS,
  PRODUCT_DETAILS_FAIL,
  PRODUCT_DETAILS_REQUEST,
  PRODUCT_DETAILS_SUCCESS,
  PRODUCT_LIST_FAIL,
  PRODUCT_LIST_REQUEST,
  PRODUCT_LIST_SUCCESS,
  PRODUCT_UPDATE_FAIL,
  PRODUCT_UPDATE_REQUEST,
  PRODUCT_UPDATE_SUCCESS,
} from '../constants/productConstants'

export const addProduct = product => async (dispatch, getState) => {
  try {
    dispatch({ type: PRODUCT_ADD_REQUEST })

    const {
      userLogin: { userInfo },
    } = getState()

// USER INFO IS 'UNDEFINED' - ERROR: CANNOT READ PROPERTY OF DATA
// ACTION WORKS WHEN REMOVING USERINFO FROM THE ACTION

    const config = {
      headers: {
        'Content-Type': 'application/json',
        Authorization: `Bearer ${userInfo.token}`,
      },
    }

    const { data } = await axios.post('/product', product, config)

    dispatch({
      type: PRODUCT_ADD_SUCCESS,
      payload: data,
    })
  } catch (error) {
    dispatch({
      type: PRODUCT_ADD_FAIL,
      payload:
        error.message && error.response.data.message
          ? error.response.data.message
          : error.message,
    })
  }
}

export const listProducts = () => async dispatch => {
  try {
    dispatch({ type: PRODUCT_LIST_REQUEST })

    const { data } = await axios.get('/product')

    dispatch({
      type: PRODUCT_LIST_SUCCESS,
      payload: data,
    })
  } catch (error) {
    dispatch({
      type: PRODUCT_LIST_FAIL,
      payload:
        error.message && error.response.data.message
          ? error.response.data.message
          : error.message,
    })
  }
}

export const listProductDetails = id => async dispatch => {
  try {
    dispatch({ type: PRODUCT_DETAILS_REQUEST })

    const { data } = await axios.get(`/product/${id}`)

    dispatch({
      type: PRODUCT_DETAILS_SUCCESS,
      payload: data,
    })
  } catch (error) {
    dispatch({
      type: PRODUCT_DETAILS_FAIL,
      payload:
        error.message && error.response.data.message
          ? error.response.data.message
          : error.message,
    })
  }
}

export const updateProduct = product => async (dispatch, getState) => {
  try {
    dispatch({ type: PRODUCT_UPDATE_REQUEST })

    const {
      userLogin: { userInfo },
    } = getState()

    const config = {
      headers: {
        'Content-Type': 'application/json',
        Authorization: `Bearer ${userInfo.token}`,
      },
    }

    const { data } = await axios.put(`/product/${product._id}`, product, config)

    dispatch({
      type: PRODUCT_UPDATE_SUCCESS,
      payload: data,
    })
  } catch (error) {
    dispatch({
      type: PRODUCT_UPDATE_FAIL,
      payload:
        error.message && error.response.data.message
          ? error.response.data.message
          : error.message,
    })
  }
}

export const deleteProduct = id => async (dispatch, getState) => {
  try {
    dispatch({ type: PRODUCT_DELETE_REQUEST })

    const {
      userLogin: { userInfo },
    } = getState()

    const config = {
      headers: {
        'Content-Type': 'application/json',
        Authorization: `Bearer ${userInfo.token}`,
      },
    }

    const { data } = await axios.delete(`/product/${id}`, config)

    dispatch({
      type: PRODUCT_DELETE_SUCCESS,
      payload: data,
    })
  } catch (error) {
    dispatch({
      type: PRODUCT_DELETE_FAIL,
      payload:
        error.message && error.response.data.message
          ? error.response.data.message
          : error.message,
    })
  }
}
Run Code Online (Sandbox Code Playgroud)

mar*_*son 201

我是 Redux 维护者,添加“createStore已弃用”消息的人:)

根据记录,这与您的实际应用程序代码无关。这专门向像您这样使用“plain Redux”的用户传达的消息 - 它试图告诉您,您正在遵循更难使用的模式,我们希望您改用 Redux Toolkit,因为它会让您的生活变得更好容易得多:)

您会注意到,这甚至不是在控制台中打印的运行时警告 - 它实际上只是编辑器中的视觉指示器,例如createStore

请参阅这些 Redux 文档页面,了解更多关于为什么我们希望人们使用 Redux Toolkit 编写 Redux 代码以及如何这样做的详细信息:

  • @markerikson 拜托,拜托,拜托,不要将弃用消息用作垃圾邮件。我知道您认为 reduxtoolkit 更好,但这是*您的*意见。我很喜欢 createSlice 模式,我不介意它成为 redux 的一部分或单独存在,但我不想要它附带的许多东西,而且我绝对不希望我的可变代码被神奇地转换变成不可变的操作。 (33认同)
  • @Guy:当然,这是“营销”,即“我们希望人们阅读本文并了解 RTK”。但这实际上就是“弃用”的首要意义:制造工具的人告诉人们使用该工具“停止以这种方式使用它,这不再是它应该使用的方式”。对于每个框架和每种语言都是如此。例如,Java 多年来一直有类似的“@deprecated”属性:https://docs.oracle.com/javase/8/docs/api/java/lang/Deprecated.html。这实际上就是它的全部要点:) (6认同)
  • @Guy:我们也希望现有的 Redux 开发人员使用 RTK,因为我们希望每个 Redux 开发人员都使用 RTK。但是,是的,有一小部分但有些直言不讳的用户_只想_单独使用 Redux 核心,并且出于各种原因不喜欢 RTK。这就是为什么这是一个“弃用”,而不是实际删除 `createStore` 的主要版本 - 我们不会破坏工作代码。但作为维护者,我们的工作是向人们指出我们认为最适合使用 Redux 的方法,这就是 RTK。 (5认同)
  • @bouffelec:请阅读[链接文章](https://redux.js.org/introduction/why-rtk-is-redux-today)。这不是“弃用消息的废弃”。这是向我们的用户发出的有意通知,即有更好的方法来编写 Redux 代码,就像任何其他将某些 API 标记为已弃用的库一样。 (4认同)
  • 我还想表达我对这种不使用折旧信息的不满。 (3认同)
  • @robbie_c:fwiw,我_非常_故意确保“弃用”仅相当于添加“@deprecated”标签,这会导致编辑器中出现视觉删除线。无运行时警告。现有代码继续按原样运行,没有任何更改,因此根本不会破坏 semver。从这个意义上说,你甚至没有_必须_去“修复”任何东西——你_可以_让你的代码保持不变,并且不会有任何问题。然而,**我们绝对希望所有 Redux 用户都使用 RTK!** 这是我们接触到许多从不查看我们文档的用户的唯一方法。(所有内容都在链接中明确说明) (2认同)
  • 是的,监听器中间件的设计目的是完成 80-90% 的 sagas 功能,包括响应操作、运行副作用,甚至分叉“子任务”……但通道是我们明确选择_不_的东西实施。如果你正在使用这些,sagas 实际上是一个有用的工具。 (2认同)

小智 50

您也可以像这样使用导入:

import { legacy_createStore as createStore } from 'redux';
Run Code Online (Sandbox Code Playgroud)

  • 通过额外的支持信息可以改进您的答案。请[编辑]添加更多详细信息,例如引文或文档,以便其他人可以确认您的答案是正确的。您可以[在帮助中心](/help/how-to-answer)找到有关如何写出好的答案的更多信息。 (2认同)

Den*_*ema 9

我收到了同样的警告,我按照 VS code 的指示做了。我导入了legacy_createStore。

import {legacy_createStore} from 'redux'
Run Code Online (Sandbox Code Playgroud)

或者您可以使用别名,以便您的代码保持不变。

import {legacy_createStore as createStore} from 'redux'
Run Code Online (Sandbox Code Playgroud)