React native + redux-persist: how to ignore keys (blacklist)?

19.8k views Asked by At

I'm storing my settings with redux-persist and would like to ignore some of them to have them reset on every restart, e.g. after a crashing.

It's possible to add an array of reducer-names as blacklist or whitelist, but I'd like to ignore specific keys, e.g. settings.isLoggedIn instead of settings.

// ...
function configureStore(initialState) {
    const store = createStore(
        RootReducer,
        initialState,
        enhancer
    );

    persistStore(store, {
        storage: AsyncStorage,
        blacklist: ['router', 'settings'] // works, 'settings.isLoggedIn' doesn't.
    }, () => {
        // restored
    });

    return store;
}
// ...

Do I have to create another reducer or does anyone a solution to this problem?

Thanks in advance!

6

There are 6 answers

0
martinarroyo On BEST ANSWER

As per the documentation, the blacklist parameter contains: 'keys (read: reducers) to ignore', so I am afraid it is not possible to implement the behaviour that you want. You can try and implement that functionality yourself, but I think the codebase of the package is really focused on blacklisting reducers instead of properties (see this). I am afraid that the only solution is to create a separate reducer for your non-persistent keys (in my experience it is not much of a hassle).

0
Ahmed Ali On

you have to create reducer for every prop you want to save.

0
Irfan wani On

As @martinarroyo mentioned to create a separate reducer which is a good option and if we follow it and create a seperate reducer for errors, we can simply return an empty state as the default;

const initialState = {
    error: null
}

export default errorReducer = (state = initialState, action) => {
    switch (action.type) {
        ...         
    
        default:
            return {
                ...state,
                error: null
            }
    }
}

This will clear the state everytime we visit the site as defualt is setting the errors to null.

0
shubham choudhary On

You can use Nested Persists for this.

import { persistStore, persistReducer } from 'redux-persist';


const rootPersistConfig = {
  key: 'root',
  storage: storage,
  blacklist: ['auth']
}

// here you can tell redux persist to ignore loginFormData from auth reducer

const authPersistConfig = {
  key: 'auth',
  storage: storage,
  blacklist: ['loginFormData']
}

// this is your global config
const rootReducer = combineReducers({
  auth: persistReducer(authPersistConfig, authReducer),
  other: otherReducer,
})

// note: for this to work, your authReducer must be inside blacklist of 
// rootPersistConfig

const myReducerConfig = {
  key: "cp",
  storage: storage,
  blacklist: ["authReducer"],
  debug: true
};


0
lokhmakov On

Use transforms for save separate fields, for example for username in redux-form MyForm inside state.form.MyForm:

const formName = `MyForm`

const formTransform = createTransform(
  (inboundState, key) => {
    return {
      ...inboundState,
      [formName]: {
        values: {
          username: _.get(inboundState, `${ MyForm }.values.username`)
        }
      }
    }
  },
  (outboundState, key) => {
    return outboundState
  },
  { whitelist: [`form`] }
)

persistStore(store, {
  whitelist: [
    `form`
  ],
  transforms: [
    formTransform
  ]
})
0
93sauu On

A simple solution is to save the whole reducer in the whitelist and after in the reducer using 'persist/REHYDRATE' action to filter only the keys that you want to keep.

Example:

// configureStore.js
const persistConfig = {
  keyPrefix: 'webapp',
  whitelist: ['filters'],
}

// filtersReducer.js
const projectsBase = {
  [KEYS.SORT]: PROJECTS_SORT_TYPE.NAME,
  [KEYS.TEXT]: '',
}
const itemsBase = {
  [KEYS.SORT]: ITEMS_SORT_TYPE.INDEX,
  [KEYS.TEXT]: '',
}

const base = {
  [KEYS.PROJECTS]: projectsBase,
  [KEYS.ITEMS]: itemsBase
}

export const filters = (state = base, action) => {
  const { type } = action
  switch (type) {
    case PERSIST_REHYDRATE_ACTION_TYPE: {
      if (action.payload.filters) {
        const filters = action.payload.filters
        const projectsSort = _.get(filters, [KEYS.PROJECTS, KEYS.SORT])
        const itemsSort = _.get(filters, [KEYS.ITEMS, KEYS.SORT])
        const newBase = { ...base, 
                         [KEYS.PROJECTS]: {
                             [KEYS.SORT]: projectsSort
                         },
                         [KEYS.ITEMS]: {
                             [KEYS.SORT]: itemsSort
                         }}
        state = newBase
      }
    }
      break
    default:
      break
  }
  return state
}