使用 redux 工具包时出现错误“在状态中检测到不可序列化的值” - 但不是普通的 redux

Haz*_*azy 48 javascript reactjs redux react-redux redux-toolkit

我正在尝试将我正在构建的应用程序切换为使用 Redux Toolkit,并且在我从 createStore 切换到 configureStore 时注意到出现此错误:

A non-serializable value was detected in the state, in the path: `varietals.red.0`. Value:, Varietal {
  "color": "red",
  "id": "2ada6486-b0b5-520e-b6ac-b91da6f1b901",
  "isCommon": true,
  "isSelected": false,
  "varietal": "bordeaux blend",
}, 
Take a look at the reducer(s) handling this action type: TOGGLE_VARIETAL.
(See https://redux.js.org/faq/organizing-state#can-i-put-functions-promises-or-other-non-serializable-items-in-my-store-state)
Run Code Online (Sandbox Code Playgroud)

在四处探索之后,我发现问题似乎出在我的自定义模型上。例如,品种数组是从品种模型创建的:

class Varietal {
  constructor(id, color, varietal, isSelected, isCommon) {
  this.id = id;
  this.color = color;
  this.varietal = varietal;
  this.isSelected = isSelected;
  this.isCommon = isCommon;
 }
}
Run Code Online (Sandbox Code Playgroud)

并使用它映射一个字符串数组来创建我的 Varietal 数组,该数组进入我的状态:

// my utility function for creating the array
const createVarietalArray = (arr, color, isCommon) =>
  arr.map(v => new Varietal(uuidv5(v, NAMESPACE), color, v, false, isCommon));';

// my array of strings
import redVarietals from '../constants/varietals/red';

// the final array to be exported and used in my state
export const COMMON_RED = createVarietalArray(redVarietals.common.sort(), 'red', true);
Run Code Online (Sandbox Code Playgroud)

当我切换模型并用返回一个普通对象数组的东西替换数组创建实用程序时:

export const createVarietalArray = (arr, color, isCommon) =>
  arr.map(v => ({
    id: uuidv5(v, NAMESPACE),
    color,
    varietal: v,
    isSelected: false,
    isCommon,
  }));
Run Code Online (Sandbox Code Playgroud)

那么对于那个 PARTICULAR 减速器,错误就消失了,但是我在我的应用程序中都有这些自定义模型,在我开始将它们全部撕掉并重新编码它们只是为了能够使用 Redux Toolkit 我想在这里问在我这样做之前真的是问题所在......

小智 82

随着getDefaultMiddleware折旧,可以通过使用来解决

   middleware: getDefaultMiddleware =>
    getDefaultMiddleware({
      serializableCheck: false,
    }),
Run Code Online (Sandbox Code Playgroud)

  • 我们可以只对一个reducer 执行这个serializedCheck false 吗? (4认同)

mar*_*son 37

是的。我们一直告诉 Redux 用户他们不应该在 store 中放置不可序列化的值。Redux Toolkit 专门设计用于帮助在设置 Redux 存储时提供良好的默认值,作为其中的一部分,它包括检查以确保您不会意外地改变您的数据,并且您不包括不可序列化的值。

类实例根据定义不是完全可序列化的,因此它正确地将这些实例标记为问题。请重写您的逻辑,不要将它们传递给商店。

通常,React 和 Redux 应用程序应该使用纯 JS 对象和数组作为数据来编写。您不需要“模型类”。

  • 这是一个糟糕的答案。它没有提供任何解决方案。“只是别这么做。” 而且它甚至没有提供不这样做的理由。显得非常刻薄和粗鲁。 (5认同)
  • 嗯。我不知道为什么你觉得有必要删除我一年前写的答案的评论。最终它是_您的_代码库,您可以用它做任何您想做的事情。但作为一般规则,React 生态系统应用程序不使用模型类,并且 Redux _has_ 始终非常固执地不允许 Redux 存储状态中的类。这就是我们给人们的建议。 (2认同)
  • 添加一种方法来控制序列化,从而允许存储我们想要和/或需要的每个值类型不是很好吗? (2认同)
  • 如果需要,您可以[自定义序列化检查中间件的行为](https://redux-toolkit.js.org/api/serializabilityMiddleware),包括覆盖“哪些值可序列化?” 回调或完全关闭它。但是,我们**强烈建议您不要这样做**。最终,这是您的应用程序,您可以做任何您想做的事情,但这些准则的存在是有原因的。 (2认同)

Rah*_*man 36

这更有可能是redux-persist. redux-toolkit在其中提供一些默认中间件getDefaultMiddleware

import { getDefaultMiddleware } from '@reduxjs/toolkit';
Run Code Online (Sandbox Code Playgroud)

您可以通过提供 false 标志来禁用每个中间件。去除serializableCheck

const customizedMiddleware = getDefaultMiddleware({
  serializableCheck: false
})
Run Code Online (Sandbox Code Playgroud)

有关详细信息,请查看redux-toolkit 文档

  • 任何看到此内容并使用 redux-persist 的人都不会完全禁用可序列化检查,除非您知道自己在做什么。最好专门禁用 redux-persist 的操作。[参见@AmerllicA的答案](/sf/answers/4382729571/) (7认同)
  • getDefaultMiddleware 现已弃用,请参阅 boluwatife-fakorede 的答案 /sf/answers/4795679731/ (2认同)

小智 31

此示例显示排除可序列化状态检查中间件,在此处输入链接描述

 const store = configureStore({
  reducer: rootReducer,
  middleware: (getDefaultMiddleware) =>
    getDefaultMiddleware({
      serializableCheck: false,
    }),
})
Run Code Online (Sandbox Code Playgroud)


Mar*_*pez 14

查看 RTK 文档,了解如何使用 Redux Persist 进行设置。

https://redux-toolkit.js.org/usage/usage-guide#use-with-redux-persist

基本上就是这一行:

middleware: getDefaultMiddleware =>
    getDefaultMiddleware({
      serializableCheck: {
        ignoredActions: [FLUSH, REHYDRATE, PAUSE, PERSIST, PURGE, REGISTER],
      },
    })
Run Code Online (Sandbox Code Playgroud)

这是在configureStore 调用中。

另外,你还需要这个:

import {
  persistStore,
  persistReducer,
  FLUSH,
  REHYDRATE,
  PAUSE,
  PERSIST,
  PURGE,
  REGISTER,
} from 'redux-persist'
Run Code Online (Sandbox Code Playgroud)


Ame*_*icA 12

React Native当我想redux-persist与 一起实施时,我遇到了这个问题@reduxjs/toolkit,我收到了这个错误:

在此处输入图片说明

然后我通过以下代码修复它:

import {
  combineReducers,
  configureStore,
  getDefaultMiddleware,
} from '@reduxjs/toolkit';
import {
  persistStore,
  persistReducer,
  FLUSH,
  REHYDRATE,
  PAUSE,
  PERSIST,
  PURGE,
  REGISTER,
} from 'redux-persist';
import storage from 'utils/storage'; // in fact it is AsyncStorage
import counter from 'reduxStore/reducers';

const persistConfig = {
  key: 'root',
  storage,
};

const reducer = combineReducers({
  counter,
});

const persistedReducer = persistReducer(persistConfig, reducer);

const store = configureStore({
  reducer: persistedReducer,
  middleware: getDefaultMiddleware({
    serializableCheck: {
      ignoredActions: [FLUSH, REHYDRATE, PAUSE, PERSIST, PURGE, REGISTER],
    },
  }),
});

export const persistor = persistStore(store);

export default store;
Run Code Online (Sandbox Code Playgroud)

实际上,这些行对我有帮助,没有它们我会遇到上述错误:

middleware: getDefaultMiddleware({
  serializableCheck: {
    ignoredActions: [FLUSH, REHYDRATE, PAUSE, PERSIST, PURGE, REGISTER],
  },
}),
Run Code Online (Sandbox Code Playgroud)

  • 这与 RTK 文档一致:https://redux-toolkit.js.org/usage/usage-guide#use-with-redux-persist (4认同)
  • @Dijiflex,我希望并祈祷您的问题能够得到解决。 (4认同)
  • 我做了同样的事情,但我得到了同样的错误。 (2认同)

小智 7

我添加了“middleWare”参数和“serializedCheck: false”,问题解决了。(实际上这不是问题)

来源:链接

 import { configureStore } from '@reduxjs/toolkit'
    import rootReducer from './reducer'
    import { myCustomApiService } from './api'
    
    const store = configureStore({
      reducer: rootReducer,
      middleware: (getDefaultMiddleware) =>
        getDefaultMiddleware({
          serializableCheck: false,
        }),
    })
Run Code Online (Sandbox Code Playgroud)