Redux persist gives me undefined states instead of default redux states

Viewed 213

I am using redux-persist and redux-persist-transform-filter for persisting some keys in my reducers. In my case, I need to persist only the filters.

This is how I configured my store:

const subscriptionsFilter = createFilter('subscriptions', ['filters']);
const rebillingFilter = createFilter('subscriptionsRebillingStatistics', [
  'filters',
]);
const negativeListFilter = createFilter('negativeList', ['filters']);
const disputesFilter = createFilter('disputes', ['filters']);
const merchantAccountsFilter = createFilter('merchantAccounts', ['filters']);
const webhooksFilter = createFilter('webhooks', ['queryParam']);
const processingStatementsFilter = createFilter('processingStatements', [
  'filters',
]);
const responseCodeOverviewFilter = createFilter('responseCodeOverview', [
  'filters',
]);
const paymentsFilter = createFilter('payments', ['sideFilters']);
const dashboardFilter = createFilter('dashboard', ['filters']);
const customersFilter = createFilter('customers', ['sideFilters']);
const binBlockingFilter = createFilter('binBlocking', ['sideFilters']);

const persistConfig = {
  key: 'root',
  storage,
  whitelist: [
    'user',
    'dashboard',
    'payments',
    'subscriptions',
    'subscriptionsRebillingStatistics',
    'negativeList',
    'disputes',
    'merchantAccounts',
    'webhooks',
    'processingStatements',
    'responseCodeOverview',
    'customers',
    'binBlocking',
  ],
  transforms: [
    subscriptionsFilter,
    rebillingFilter,
    negativeListFilter,
    disputesFilter,
    merchantAccountsFilter,
    webhooksFilter,
    processingStatementsFilter,
    responseCodeOverviewFilter,
    paymentsFilter,
    dashboardFilter,
    customersFilter,
    binBlockingFilter,
  ],
};

const persistedReducer = persistReducer(persistConfig, rootReducer);

const middlewares = [thunkMiddleware];
const middlewareEnhancer = applyMiddleware(...middlewares);

const enhancers = [middlewareEnhancer];
const composedEnhancers = composeWithDevTools(...enhancers);

export const store = createStore(persistedReducer, composedEnhancers);

export const persistor = persistStore(store, {}, () => {
  const user = store.getState().user.user;

  if (!!user) {
    setAccessToken(user);
  }
})

;

My app is now crashing because it's trying to read something from undefined states. For example if I want to use something I have to add fallback || {} in my component like this:

   const { subscriptionCardInformation, isSubscriptionCardInformationLoading } =
    useSelector((state: State) => state.subscriptions);

  const {
    cardholder_name,
    masked_pan,
    bin_country,
    is_bin_blocking,
    is_prepaid,
    type,
    expiration_month,
    expiration_year,
    reference,
    scheme,
  } = subscriptionCardInformation || {};

Is there any better way to do it with redux-persist?

1 Answers

For anyone coming across this (as I did), the concept you're looking at to address this issue is redux-persist migrations.

We can think of the redux-persist persisted data as a database in our local storage. Much like a traditional database, when we make schema changes we need to write a migration to detail how to update the existing tables to support the new schema. Sometimes this is as simple as adding fields, sometimes it's much more complex and involves moving data around.

Regardless of what you need to do, you can find out more information from the official docs

In your case, any time you modify any of the state defined in your whitelist you would have to write a migration to tell redux-persist how to update the persisted data.

So lets assume you newly added state.subscriptions to your store (based on your question), you would need a migration as such:

store

const migrations = {
  0: state => {
    return {
      ...state,
      settings: {
        ...state.settings,
        subscriptions: defaultSubscriptionsState,
      },
    };
  },
};

const persistConfig = {
  key: 'root',
  version: 0, // Defaults to -1, must be an incrementing number which matches a key in your migrations
  storage,
  whitelist: [
    'user',
    'dashboard',
    'payments',
    'subscriptions',
    'subscriptionsRebillingStatistics',
    'negativeList',
    'disputes',
    'merchantAccounts',
    'webhooks',
    'processingStatements',
    'responseCodeOverview',
    'customers',
    'binBlocking',
  ],
  transforms: [
    subscriptionsFilter,
    rebillingFilter,
    negativeListFilter,
    disputesFilter,
    merchantAccountsFilter,
    webhooksFilter,
    processingStatementsFilter,
    responseCodeOverviewFilter,
    paymentsFilter,
    dashboardFilter,
    customersFilter,
    binBlockingFilter,
  ],
  // Add our migrations
  migrate: createMigrate(migrations, { debug: false }),
};
Related