rt2zz / redux-persist

persist and rehydrate a redux store
MIT License
12.94k stars 866 forks source link

Can't add new initial state #1270

Open bsor-dev opened 3 years ago

bsor-dev commented 3 years ago

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 }
manjuy124 commented 3 years ago

@rosnaib11 did you find any solution?

bsor-dev commented 3 years ago

@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.

aschmid commented 3 years ago

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.

parth-koshta commented 3 years ago

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

sameer0075 commented 2 years ago

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

parth-koshta commented 2 years ago

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

Brenndoerfer commented 2 years ago

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

@rosnaib11 / @sameer0075 what worked for me was:

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 }),
};
arsensgitacc commented 2 years ago

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'] },
    ),
  ],
};