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

IT技术 javascript reactjs redux react-redux redux-toolkit
2021-04-19 06:51:43

我正在尝试将我正在构建的应用程序切换为使用 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)

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

class Varietal {
  constructor(id, color, varietal, isSelected, isCommon) {
  this.id = id;
  this.color = color;
  this.varietal = varietal;
  this.isSelected = isSelected;
  this.isCommon = isCommon;
 }
}

并使用它映射一个字符串数组来创建我的 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);

当我切换模型并将数组创建实用程序替换为返回一个简单的对象数组时,如下所示:

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

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

4个回答

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

import { getDefaultMiddleware } from '@reduxjs/toolkit';

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

const customizedMiddleware = getDefaultMiddleware({
  serializableCheck: false
})

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

[2021/10/07] 编辑

要详细了解为什么会发生此错误,以及为什么设置serializableCheck为 false 会修复它,请阅读使用不可序列化数据 | 使用指南redux 工具包文档。

此外,getDefaultMiddleware导出正在被弃用,以支持使用回调表单。请参阅未来规划:RTK 2.0?· 问题 #958 · reduxjs/redux-toolkitgetDefaultMiddleware 已弃用 · 问题 #1324 · reduxjs/redux-toolkit了解更多原因。

至于它被替换的内容,请参阅getDefaultMiddleware | Redux Toolkit文档以了解更多信息:

import { configureStore } from '@reduxjs/toolkit'

import rootReducer from './reducer'

const store = configureStore({
  reducer: rootReducer,
  middleware: (getDefaultMiddleware) => getDefaultMiddleware(),
})
感谢@DakoJunior 的提醒,编辑了答案以包含其被弃用的原因以及如何使用新的回调语法的链接。
2021-05-27 06:51:43
谢谢大佬,你救了我!这应该是公认的答案。
2021-06-09 06:51:43
任何看到这一点并使用 redux-persist 的人,除非您知道自己在做什么,否则不要完全禁用可序列化检查。最好专门禁用来自 redux-persist 的操作。请参阅@AmerllicA 的答案
2021-06-09 06:51:43
getDefaultMiddleware 现在已弃用,请参阅boluwatife-fakorede 的答案stackoverflow.com/a/68509710/10765649
2021-06-14 06:51:43
在我的情况下,它可能是由redux-saga以下原因引起的 上面的A non-serializable value was detected in an action, in the path: 类型. Value: ƒ actionCreator() { var args = []; for (var _i = 0; _i < arguments.length; _i++) { args[_i] = arguments[_i]; } if (prepareAction) 选项抑制了错误,但我认为这不是正确的解决方法。
2021-06-18 06:51:43

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

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

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

嗯。我不知道你为什么觉得有必要在我一年前写的一个答案上放弃这个评论。最终它是你的代码库,你可以用它做任何你想做的事情。但作为一般规则,阵营生态系统的应用程序不使用模型类,和终极版一直很自以为是约不允许在店内Redux的状态类。所以,这就是我们给人们的建议。
2021-05-23 06:51:43
这是一个糟糕的答案。它没有提供任何解决方案。“只是不要这样做。” 它甚至没有提供不这样做的理由。显得非常尖刻和粗鲁。
2021-06-01 06:51:43
如果需要,您可以自定义序列化检查中间件的行为,包括覆盖“哪些值是可序列化的?” 回调或完全关闭它。但是,我们强烈建议您不要这样做最终它是你的应用程序,你可以做任何你想做的事,但这些准则的存在是有原因的。
2021-06-08 06:51:43
老实说,在这种情况下,您可能不想使用 Redux :)
2021-06-09 06:51:43
添加一种控制序列化的方法从而允许存储我们想要和/或需要的每个值类型不是很好吗?
2021-06-12 06:51:43

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;

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

middleware: getDefaultMiddleware({
  serializableCheck: {
    ignoredActions: [FLUSH, REHYDRATE, PAUSE, PERSIST, PURGE, REGISTER],
  },
}),
我做了同样的事情,但我得到了同样的错误。
2021-05-26 06:51:43
@Dijiflex,我希望并祈祷您的问题得到解决。
2021-05-26 06:51:43
2021-06-16 06:51:43

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

   middleware: getDefaultMiddleware =>
    getDefaultMiddleware({
      serializableCheck: false,
    }),
我们可以只为一个减速器执行这个 serializableCheck false 吗?
2021-05-24 06:51:43