redux-persist icon indicating copy to clipboard operation
redux-persist copied to clipboard

Can't add new initial state

Open bsor-dev opened this issue 4 years ago • 8 comments

In development mode, if I want to add new state under whitelist. The new state I added doesn't appear. I need to clear the storage of my app in able to see the new state that I added. Is that normal or I got some mistake?

Example, I wanna add new initial state under user store

{ 
   checkout: {
       loading: false,
       error: null
   }
}

then even if I reload my app it doesn't appear when I call and when I check the checkout.

const checkout = useSelector((state) => state.user.checkout) undefined

So to make it appear on state.

1.) is I will remove the user store at whitelist then reload the app, then return it back to whitelist 2.) clear storage of the app

Here's how I config my store

import AsyncStorage from '@react-native-async-storage/async-storage'
import { combineReducers } from 'redux'
import {
  persistReducer,
  persistStore,
  FLUSH,
  REHYDRATE,
  PAUSE,
  PERSIST,
  PURGE,
  REGISTER,
} from 'redux-persist'
import { configureStore } from '@reduxjs/toolkit'

import startup from './Startup'
import user from './User'
import theme from './Theme'
import utils from './Utils'

const reducers = combineReducers({
  startup,
  user,
  theme,
  utils,
})

const persistConfig = {
  key: 'root',
  storage: AsyncStorage,
  whitelist: ['theme', 'user'],
}

const persistedReducer = persistReducer(persistConfig, reducers)

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

    if (__DEV__ && !process.env.JEST_WORKER_ID) {
      const createDebugger = require('redux-flipper').default
      middlewares.push(createDebugger())
    }

    return middlewares
  },
})

const persistor = persistStore(store)

export { store, persistor }

bsor-dev avatar Jan 21 '21 23:01 bsor-dev

@rosnaib11 did you find any solution?

manjuy124 avatar Jan 29 '21 15:01 manjuy124

@manjuy124 No. What I did just separate my unnecessary states to other non-persisted modules. And add only those required state to whitelist such as token, userinfo.

bsor-dev avatar Jan 29 '21 15:01 bsor-dev

having the same issue. this is kind of a problem in my opinion. what if i want to add new persisted states to my app i can't ask everybody who uses my app to clear their localstorage.

aschmid avatar Jun 15 '21 20:06 aschmid

You can use Migrations for your use case - https://github.com/rt2zz/redux-persist/blob/master/docs/migrations.md

parth-koshta avatar Jul 20 '21 06:07 parth-koshta

@parth-koshta i have used as provided in the link but still my new states are not being shown

sameer0075 avatar Feb 04 '22 06:02 sameer0075

@sameer0075 Did you update the version key in persistConfig to your latest migration key?

parth-koshta avatar Feb 04 '22 06:02 parth-koshta

Thanks @parth-koshta for pointing us towards the migration example.

@rosnaib11 / @sameer0075 what worked for me was:

  • I added the initialState hanFontSize: 24 in my slice
  • I did not manage to get it to work without stateReconciler: autoMergeLevel2 - maybe I was manually overwriting the state with a wrong format, but this works well for me.
  • https://github.com/rt2zz/redux-persist#state-reconciler a more conservative reconciler might work for you

After making changes to your migration code, bump the version by one.

import autoMergeLevel2 from 'redux-persist/es/stateReconciler/autoMergeLevel2';

const migrations: any = {
    0: (state: RootState) => {
        // migration clear out device settings
        return {
            ...state,
            // settings: undefined
        }
    },
    1: (state: RootState) => {
        // migration to keep only device state
        return {
            settings: {
                hanFontSize: 24
            }
        }
    }
}
const persistConfig = {
    key: "root",
    version: 5,
    storage: AsyncStorage,
    blacklist: ['quiz'],
    stateReconciler: autoMergeLevel2,
    migrate: createMigrate(migrations, { debug: true }),
};

Brenndoerfer avatar Feb 14 '22 12:02 Brenndoerfer

You can use migration, as described in this post

Or you can use transform


const persistConfig = {
  key: 'your_key',
  version: 1,
  storage: AsyncStorage,
  whitelist: ['your_reducer_1', 'your_reducer_2'],
  transforms: [
    createTransform(
      // transform state on its way to being serialized and persisted.
      (inboundState: RootState, key) => {
        return inboundState;
      },
      // transform state being rehydrated
      (outboundState: RootState, key) => {
        switch (key) {
          case 'your_reducer_1':
            return { ...reducer1InitialState, ...outboundState };
          case 'your_reducer_2':
            return { ...reducer1InitialState, ...outboundState };
          default:
            return outboundState;
        }
      },
      // define which reducers this transform gets called for.
      { whitelist: ['your_reducer_1', 'your_reducer_2'] },
    ),
  ],
};

arsensgitacc avatar Apr 11 '22 13:04 arsensgitacc