First, we’ll set up persistent storage for our app. For this, we’ll use an excellent and easy-to-use library called redux-persist. Most of you must be familiar with redux. For those unfamiliar, it is a simple way to manage and share data in your React and React Native apps across various components and views. You can read more about it in my article on redux and how to use it in React and React Native apps.
Open the terminal and type the following command on your project’s root directory:
npm i redux-persist
This command will install redux-persist, which will help us to retain our data from previous sessions.
note
We’ll use redux-promise as our middleware for the examples in this article. You can use any middleware, like redux-saga or redux-thunk, based on your requirements!
Now let’s set up our store to make it persistent — so that the next time our app loads up, we’ll have data saved from the previous session. On your main store.js, set up persistent storage like this:
import { combineReducers, createStore, applyMiddleware } from 'redux';import storage from 'redux-persist/lib/storage';import { persistReducer, persistStore } from 'redux-persist';import promise from 'redux-promise';// Create the root reducer as you normally would.const rootReducer = combineReducers({ myPersistentData: dataReducer, someMorePresistentData: randomReducer,});/* Create the configuration object to be used for transforming our simpleroot reducer into a property on persistent storage.*/const config = { key: '_myPersistentDataKey', storage,};// Make your reducer persistent with persistReducer()const reducer = persistReducer(config, rootReducer);const store = createStore( reducer, // Your persistent reducer {}, // Initial store state applyMiddleware(promise), // middleware(s));// Convert your store to be persistent accross app sessions.const persist = persistStore(store);export default { store, persist };
In the main App.js file, modify the render function like this:
import { PersistGate } from "redux-persist/integration/react";import { Provider } from "react-redux";import store from "./store";import MyRootComponent from "./src";class App extends Component { constructor(props) { super(props); // ... } render() { return ( <Provider store={store.store}> <PersistGate persistor={store.persist}> <MyRootComponent /> </PersistGate> </Provider> ); }}export default App;
That’s it! We’ve set up our redux state to be persistent! Easy.
Encrypting Persisted Data
For this, we’ll use redux-persist-transform-encrypt. Run the following command on your project’s root directory:
npm i redux-persist-transform-encrypt
This will help us encrypt and decrypt user data across multiple sessions.
important
Since this was just an example of how to encrypt your data, we hard-coded our secret key into the source code, but you must never do that! Ideally, it would be injected during our build process.
Now, open the store.js file again and update it to look like this:
import { combineReducers, createStore, applyMiddleware } from 'redux';import storage from 'redux-persist/lib/storage';import { persistReducer, persistStore } from 'redux-persist';import promise from 'redux-promise';import createEncryptor from 'redux-persist-transform-encrypt'; // <----- Import createEncryptorconst rootReducer = combineReducers({ myPersistentData: dataReducer, someMorePresistentData: randomReducer,});/* Configure your encryptor with the secret key NOTE: This secret key is required for access to data. If the key is incorrect or changed after storing data with some different key, it will return null.*/const encryptor = createEncryptor({ secretKey: 'my-not-so-secret-encryption-key', onError: (error) => { console.warn('error occured on encryptor', error); },});const config = { key: '_myPersistentDataKey', storage, /* Add the encryptor as a transform property. This is will tell the persistent storage to encrypt data using the configuration given earlier,i.e., our secretKey. */ transforms: [encryptor], // <----- Add this line.};const reducer = persistReducer(config, rootReducer);const store = createStore( reducer, {}, applyMiddleware(promise),);const persist = persistStore(store);export default { store, persist };
Awesome! We made the data in our store state persistent locally, along with encryption! 🎉 👏