Persistence , as the English Dictionary defines it, is the property of being persistent(persistent meaning obstinately refusing to give up or let go ). Even as persistence in redux or programming in general might be a lot less dramatic, it is a pretty similar logic.
Persistence is therefore (in this context of this article) defined as the property of a data to continue to exist even after the execution of the program.
The application of persistence is used in almost every single web application on the internet. Examples of the practical uses of persistence are, storing of user sign up/signin info, storing of cart items in an e commerce website, storing of liked songs in music platforms like deezer, spotify etc. A data can be said to be persistent if, for example, remains even after a webpage has been reloaded or sometimes shut down completely and reopened, and this can only happen to a data, either after it’s been stored in the window, or in a database. However in this redux article we shall be focusing on the former.
There are 2 kinds of storage :
- Local Storage.
- Session Storage.
These two kinds of storage work or get used in almost the same kind of manner as they use the exact same methods, setItem and getItem. The difference between them is that Session storage persists the data as long as the tab is opened, which translates into that even if we refresh our tab we can still retrieve our data, we only lose our data once we close the tab.
Local storage on the other hand persists the data even after we've closed our tab, until we clear it out.
The methods setItem and getItem as the name, I think suggests, are used to “set" the data in the storage and “get”/ pull out the data from the storage respectively. Sounds pretty simple right? The catch(not so much of a catch though) is that we can only store strings. Thankfully with our knowledge of JSON (JavaScript Object Notation) we can store data in an object then we turn objects to JSON ( which is just basically the string version of a JavaScript object ).
Example:
const storedExample = { name: ‘JavaScript’ };
const jsonStoredExample = JSON.stringify(storedExample);
window.localStorage.setItem(‘storedItem', jsonStoredExample);
In the example above we store the object ‘storedExample' in the local storage. In order to do that we turn the object first to a string using the JSON.stringify() method, which turns JavaScript objects to JSON, then we store the JSON object, using the setItem method discussed in the paragraph above, with the key ‘storedItem' (whose importance would be evident when we try to retrieve the data)
const retrieveJsonStoredExample = window.localStorage.getItem(‘storedItem');
// “{ “name" : “JavaScript” }”
JSON.parse( retrieveJsonStoredExample );
// { name: “JavaScript" }
In the code block above, we try ( and succeed ) to retrieve the data previously stored using the getItem method, but as we would expect, the data is in json, to turn it to an object, we use the parse method. Note how the key we used to store the data previously was used to retrieve the data, the key should be and is unique to the data we are trying to store so as to effectively retrieve the data.
Redux Persist. Persistence in redux, uses the same logic in the background, as getting access to the persistence property in redux is more of installing and configuring much more than actually writing out code.
These steps are outlined below:
- First we start of by installing the redux-persist library.
npm install redux-persist
Or if you rather use yarn
yarn add redux-persist
- We import the persistStore method into our store(where we keep our root reducer and middlewares like redux-logger ) .
Import { createStore, applyMiddleware } from ‘redux';
Import { persistStore } from ‘redux-persist';
Import logger from ‘redux-logger';
Import rootReducer from ‘root-reducer’;
const middlewares = [ logger ];
const store = createStore( rootReducer, applyMiddleware(...logger));
const persistor = persistStore(store);
export default { store, persistor };
The persistStore method imported from the redux-persist library takes in the store and returns a persisting version of the store.
- Just as we imported the persistStore method to give the store the property of persistence, we import the persistReducer method in the root reducer file to persist the root reducer, which is basically all the reducers combined.
Import { persistReducer } from ‘redux-persist';
Import { combineReducers } from ‘redux';
Import storage from ‘redux-persist/lib/storage'; // this is however for the persistence property that local storage offers.
For Session storage:
import storage from 'redux-persist/lib/storage/session ;
- In the same root reducer file we create the persistConfig object.
const persistConfig = {
key: ‘root',
storage: ‘storage',
whitelist: [ what reducer or data you want to have the persist property ]
}
The persistConfig object has the key property whose value specifies from what part of the reducer do we want to start storing everything, in which to that we say, the root.
The storage property signifies the storage property we are trying to use ( session storage or local storage ).
The whitelist property is an array whose value is the string name of any of the reducer we are trying to give the persist property to.
- We pass in the persistConfig object and the root reducer as parameters into the persistReducer method we imported in step 3.
const rootReducer = combineReducers({
// name and value properties of the reducers you have created.
})
export default persistReducer( persistConfig, rootReducer );
- Finally we import the PersistGate component, that will enable us to use the persistor(the persisted store) in our application, into our index.js file from the redux-persist library we imported , we then wrap the app.js with the PersistGate component.
Import { PersistGate } from ‘redux-persist/integration/react';
Import { Provider } from ‘ react-redux';
Import { persistor, store} from ‘store’;
ReactDOM.render(
<Provider store = { store } >
<PersistGate persistor = { persistor } >
<App/>
</PersistGate>
</Provider>,
document.getElementById(‘root')
)
The Provider component which wraps the entire App enables us use store in our App, while the PersistGate allows us to use the persisted version of the store in our App.
Now our store and root reducer which are basically the overall state of the program now possesses the property of persistence.
DISCLAIMER: In as much as this article tries to explain concepts that might not be familiar, it is imperative that you know and understand Redux before applying the redux persist part of this article, as some of the lines of codes not important to redux-persist were not included.
Conclusion
Persistence in most applications, I think, is not a feature but a necessity.
Thank you.