Getting an error “A non-serializable value was detected in the state” when using redux toolkit - but NOT with normal redux

僤鯓⒐⒋嵵緔 提交于 2020-11-28 04:43:04

问题


I am trying to switch an app I am building over to use Redux Toolkit, and have noticed this error coming up as soon as I switched over to configureStore from createStore:

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)

After poking around I found the issue seems to be with my custom models. For example the varietals array is created from a varietal model:

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

and using that I map over an array of strings to create my Varietal array which goes into my state:

// 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);

When I switched out the model and replaced the array creating utility with something that returned a plain array of objects like this:

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

then that got the error to go away for that PARTICULAR reducer, however I have these custom models all through my app and before I start ripping them all out and recoding them simply to be able to use the Redux Toolkit I wanted to ask here if that is REALLY what the issue is before I did that...


回答1:


Yes. We've always told Redux users they should not put non-serializable values in the store. Redux Toolkit was specifically designed to help provide good defaults when setting up a Redux store, and as part of that, it includes checks to make sure you're not accidentally mutating your data and that you're not including non-serializable values.

Class instances are by definition not fully serializable, so it's correctly flagging those instances as a problem. Please rewrite your logic to not pass those in to the store.

In general, React and Redux apps should be written using only plain JS objects and arrays as data. You don't need "model classes".




回答2:


This is more likely a problem from 'redux-persist'. 'redux-toolkit' provide few default middleware within it's 'getDefaultMiddleware'

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

You can disable each middleware by providing false flag. To remove 'serializableCheck'

`const customizedMiddleware = getDefaultMiddleware({
    serializableCheck: false
 })`

For details check redux-toolkit documentation -

https://redux-toolkit.js.org/api/getDefaultMiddleware#:~:text=One%20of%20the%20goals%20of,checks%20for%20two%20common%20issues%3A&text=(Forked%20from%20redux%2Dimmutable%2Dstate%2Dinvariant%20.)




回答3:


I faced this issue on React Native when I wanted to implement redux-persist alongside @reduxjs/toolkit, and I got this error:

Then I fixed it by following codes:

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;

Actually, these lines help me, without them I got above error:

middleware: getDefaultMiddleware({
  serializableCheck: {
    ignoredActions: [FLUSH, REHYDRATE, PAUSE, PERSIST, PURGE, REGISTER],
  },
}),


来源:https://stackoverflow.com/questions/61704805/getting-an-error-a-non-serializable-value-was-detected-in-the-state-when-using

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!