redux-persist: non-serializable value error

Hi folks đź‘‹,

I just installed the redux-persist in a project still in its early stages and I’m facing this error message in the console as first thing when the page loads. I haven’t done much besides including the lib as is, and my reducers are pretty simple for now, so I believe it has something to do with redux-persist itself?

Error:

index.js:1446 A non-serializable value was detected in an action, in the path: `register`. Value: Ć’ register(key) {
    _pStore.dispatch({
      type: _constants__WEBPACK_IMPORTED_MODULE_2__["REGISTER"],
      key: key
    });
  }

Code above is followed by this message:

SS of the whole thing: image

Could anyone help me pointing me in the right direction? It does not break the application, but the error message is there in the console.

Cheers,

About this issue

  • Original URL
  • State: closed
  • Created 5 years ago
  • Reactions: 26
  • Comments: 26

Commits related to this issue

Most upvoted comments

For anyone else struggling to find out what [someReduxPersistActionType] should be, here’s my redux-starter-kit & redux-persist config

import React from "react";
import ReactDOM from "react-dom";
import { configureStore, getDefaultMiddleware } from "redux-starter-kit";
import { Provider } from "react-redux";
import {
  persistStore,
  persistReducer,
  FLUSH,
  REHYDRATE,
  PAUSE,
  PERSIST,
  PURGE,
  REGISTER
} from "redux-persist";
import storage from "redux-persist/lib/storage";
import { PersistGate } from "redux-persist/integration/react";

import App from "./App";
import rootReducer from "./reducers";

const persistConfig = {
  key: "root",
  version: 1,
  storage
};

const persistedReducer = persistReducer(persistConfig, rootReducer);

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

let persistor = persistStore(store);

ReactDOM.render(
  <Provider store={store}>
    <PersistGate loading={null} persistor={persistor}>
      <App />
    </PersistGate>
  </Provider>,
  document.getElementById("root")
);

There’s a solution since redux-starter-kit@0.70

Now you can opt-out the serialization using serializableCheck attr:

import { configureStore, getDefaultMiddleware } from 'redux-starter-kit'

// ...

export const store = configureStore({
  reducer,
  middleware: getDefaultMiddleware({
    serializableCheck: false,
  }),
})

We just added a section on this to the RTK Usage Guide page, here:

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

Or, ignore a specific action type for the check:

export const store = configureStore({
  reducer,
  middleware: getDefaultMiddleware({
    serializableCheck: {
        ignoredActions: [someReduxPersistActionType]
    }
  }),
})

@SeedyROM I removed the getDefaultMiddleware from the list of middlewares. There is no real fix there, it is a problem between opinions. The serializable-state-invariant-middleware complains when it sees a non-serializable object, a function in this case, being passed as an action; redux-persist needs to do so. Sometimes you just have to pick a side 🤷‍♀️ .

Anyway, here’s my configureStore.

const store = configureStore({
  reducer: rootReducer,
  middleware: [thunk, logger]
})
+ import { configureStore, getDefaultMiddleware } from "@reduxjs/toolkit";

export const store = configureStore({
  reducer: persistedReducer,
+ middleware: getDefaultMiddleware({
+   serializableCheck: {
+     ignoredActions: ["persist/PERSIST"],
    },
  }),
});

for me this fixed the issue.

@rikinshah23 You need to configure the store as in my comment above


const persistedReducer = persistReducer(persistConfig, rootReducer);

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

@SeedyROM I’m using them as they come, no custom config.

import logger from 'redux-logger'
import thunk from 'redux-thunk'

You might have to install those yourself, although I believe redux-starter-kit will have them already, I think it is better to have more atomic dependencies.

About the PersistGate error you mentioned, I never saw this, I’m sorry. Also, don’t code while sleepy, man! hahaha

Are you using redux-starter-kit? It looks like the message is caused by the included serializable-state-invariant-middleware (https://redux-starter-kit.js.org/api/getdefaultmiddleware).

As far as I can tell, passing the register and rehydrate functions in the action is central to how redux-persist currently works, but the message can be suppressed by modifying the store configuration to not include that particular middleware function.

redux-starter-kit

getDefaultMiddleware() has now moved to @reduxjs/toolkit, and could be used by getting it in the argument of the callback function like this

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

Same issue for me, redux-persist is using default redux configuration and redux-starter-kit is waiting for a string.

It would be nice to have a property into configureStore like persist: true inside redux-starter-kit and handling this error by using the immer pattern from redux-starter-kit

ty @rseemann

Are there any differences between these two?

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

because both works for me.

@aldreth Thanks I was able to solve the issue. I was directed to your solution and had help from @markerikson on a separate thread that I created.

@aldreth Thanks for the code 👍

I am using redux-persist with redux toolkit. here is my store configuration.

I haven’t implemented or configured store before. I intend to persist user state after login. Currently after login, if I reload app in emulator it always goes back to login screen.

is my store configured properly?

import {configureStore} from '@reduxjs/toolkit';
import authReducer from '../features/login/authSlice';
import AsyncStorage from '@react-native-community/async-storage';
import {persistReducer, persistStore} from 'redux-persist';
import {combineReducers} from 'redux';
import hardSet from 'redux-persist/lib/stateReconciler/hardSet';
import autoMergeLevel2 from 'redux-persist/lib/stateReconciler/autoMergeLevel2';

const reducers = combineReducers({
  auth: authReducer,
  // other reducers goes here...
});

const persistConfig = {
  key: 'root',
  storage: AsyncStorage,
//  stateReconciler: hardSet,
};

const _persistedReducer = persistReducer(persistConfig, reducers);

export const store = configureStore({
  reducer: _persistedReducer,
});
export const persistor = persistStore(store);

Here in index.js, I use PersistGate

import React from 'react';
import {AppRegistry} from 'react-native';
import App from './App';
import {name as appName} from './app.json';
import {store, persistor} from './src/stores/store';
import {Provider} from 'react-redux';
import {storeUser, storeRefreshToken} from './src/features/login/authSlice';
import {PersistGate} from 'redux-persist/lib/integration/react';

const RNRedux = () => (
  <Provider store={store}>
    <PersistGate loading={null} persistor={persistor}>
      <App />
    </PersistGate>
  </Provider>
);
AppRegistry.registerComponent(appName, () => RNRedux);

image

quem ainda tiver o mesmo problema atualmente , eu resolvi desse jeito :

export const store = configureStore({ middleware: (getDefaultMiddleware) => getDefaultMiddleware({ serializableCheck: false, }), redutor: { user: persistedReducer, }, });

For anyone else struggling to find out what [someReduxPersistActionType] should be, here’s my redux-starter-kit & redux-persist config

import React from "react";
import ReactDOM from "react-dom";
import { configureStore, getDefaultMiddleware } from "redux-starter-kit";
import { Provider } from "react-redux";
import {
  persistStore,
  persistReducer,
  FLUSH,
  REHYDRATE,
  PAUSE,
  PERSIST,
  PURGE,
  REGISTER
} from "redux-persist";
import storage from "redux-persist/lib/storage";
import { PersistGate } from "redux-persist/integration/react";

import App from "./App";
import rootReducer from "./reducers";

const persistConfig = {
  key: "root",
  version: 1,
  storage
};

const persistedReducer = persistReducer(persistConfig, rootReducer);

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

let persistor = persistStore(store);

ReactDOM.render(
  <Provider store={store}>
    <PersistGate loading={null} persistor={persistor}>
      <App />
    </PersistGate>
  </Provider>,
  document.getElementById("root")
);

This should be added to README here regarding the compatibility between redux-persist and redux-toolkit and redux-starter-kit, because redux-toolkit and redux-starter-kit are pretty commonly used.

That is exactly what is going on. Further investigating I noticed this in the default middleware. I’ll just remove the middleware, since it’s not really essential to what I’m doing.

Cheers!