قالب وردپرس درنا توس
Home / Tips and Tricks / How to Keep Your Redux Store – CloudSavvy IT

How to Keep Your Redux Store – CloudSavvy IT



Illustration with the Redux logo

Redux simplifies status management in complex applications. Since the Redux store has the full state of your app, you can save it and restore the user’s session.

Create your store

We assume that you are familiar with the basics of Redux.

For this tutorial, we’ll be using a barebones shop with a naive reducer.

import {createStore} from "redux";
 
const state = {authenticated: false};
 
const reducer = (state, action) => ({...state, ...action});
 
const store = createStore(reducer, state);

This trivial example is the basis for a Redux store that can keep track of whether we are logged in. Most users expect to stay signed in when they return to your app. At this point, the status is recreated every time the app is loaded, so users remain authenticated only during the current session.

Add Redux Persist

Redux Persist is a popular library that allows you to add persistence to the store. The library will automatically save the store every time the status is updated. You don’t have to write a persistence code in your promotions or reducers.

Start installing Redux Persist with npm:

npm install redux-persist

You now need to connect the library to your store. Wrap up your carrot reducer with Redux Persist’s persistReducer function. This allows Redux Persist to inspect the actions you send to your store. You must also call persistStore() to start the endurance.

import {createStore} from "redux";
import {persistStore, persistReducer} from "redux-persist";
import storage from "redux-persist/lib/storage";
 
const state = {authenticated: false};
 
const reducer = (state, action) => ({...state, ...action});
 
const persistConfig = {
    key: "root",
    storage
};
 
const persistedReducer = persistReducer(persistConfig, reducer);
 
const store = createStore(persistedReducer, state);
 
const persistor = persistStore(store);

This configuration is now ready for use. With just a few lines of code, we’ve made sure that changes to the Redux state are automatically enforced. Each time users reload your app, they will no longer be logged out.

Our reducer has been improved through persistReducer() to include persistence support. This newly packaged reducer is then passed on to createStore() instead of the original. And last but not least, persistStore() is invoked, passing through the store instance, to allow persistence.

Configure Redux Persist

The persistReducer() function accepts a configuration object as its first parameter. You have to key and storage properties.

key sets the name of the top-level property in the persistent object. The state of your store is stored as the value of this property.

storage defines the storage engine to use. Redux Persist supports several different storage backends depending on the environment. For use on the Internet it is localStorage and sessionStorage APIs are supported as well as basic cookies. Options are also available for React Native, Node.js, Electron, and several other platforms.

You define the storage engine to use by importing it from the package. The main API implementing object must then be passed as the storage option for Redux Persist.

You can implement your own storage engine to use a custom persistence mechanism. Create an object with setItem() getItem() and removeItem() methods. Redux Persist is asynchronous, so each method must return a promise that will be resolved when the operation is complete.

The Persistor object

The persistor object returned from persistStore() calls has a few utility methods you can use to manage persistence.

You can pause and resume persistence with the pause() and resume() methods respectively. You can force an immediate write to the storage engine with flush()This can be useful if you want to guarantee that your condition will persist after a particular surgery.

You can remove all persistent data from the storage engine with .purge()In most cases, this should be avoided – you’ll need to use a Redux action to clear your store, which will then be automatically passed to the persistent data.

State reconciliation

Redux Persist supports three different ways to hydrate your store from a sustained state. Hydration takes place automatically when you call persistStore() and existing data is found in the storage engine. Redux Persist needs to inject that initial data into your store.

The standard strategy is to merge objects to one level deep. All nested objects are not merged – the incoming change will overwrite anything already in your state.

  • Persistent State: {"demo": {"foo": "bar"}}
  • In store: {"demo": {"example": test"}}
  • Resulting hydrated shop: {"demo": {"foo": "bar"}}

You can optionally switch to merging objects to deeper levels. Import the new status tuner and add it to your store’s configuration:

// usual imports omitted
import autoMergeLevel2 from "redux-persist/lib/stateReconciler/autoMergeLevel2";
 
const persistConfig = {
    key: "root",
    storage,
    stateReconciler: autoMergeLevel2
};
 
// store configuration omitted

Here is the result of it autoMergeLevel2 would be when hydrating the example above:

  • Persistent State: {"demo": {"foo": "bar"}}
  • In store: {"demo": {"example": test"}}
  • Resulting hydrated shop: {"demo": {"foo": "bar", "example": "test"}}

The values ​​of the demo properties of the two sources are combined in the hydration.

Use the hardSet reconciler if you want to turn merge off altogether. This will replace the state of the store with the contents of the storage engine. This is often undesirable as it makes migrations more complicated – adding a new initial property to your state will disable it for existing users once their session hydrates.

Migrate your state

Regarding migrations, Redux Persist has built-in support for upgrading from persisted state to a new version. Sometimes you replace properties with newer alternatives. You must ensure that existing users do not need to reset your app to continue using it.

Migrations are configured with the migrate configuration key. The simplest approach is to pass a function that takes the status as a parameter and returns the migrated status. You also need it version configuration key so that Redux Persist can identify when migrations are needed. Every time the version changes, your migration function is called.

const persistConfig = {
    key: "root",
    storage,
    version: 1,
    migrate: (state) => ({...state, oldProp: undefined, newProp: "foobar"});
};

As an alternative to the function approach, you can pass an object that allows individual migration functions to be created for each version step. This must be passed on to it createMigrate() function before it is handed over to the Redux Persist configuration.

// other imports omitted
import {createMigrate} from "redux-persist";
 
const migrations = {
    1: state => ({...state, extraProp: true}),
    2: state => ({...state, extraProp: undefined, extraPropNew: true})
};
 
const persistConfig = {
    key: "root",
    storage,
    version: 2,
    migrate: createMigrate(migrations)
}

In this example, we initialize the store as version 2. If the state already existed on the user’s device as version 0, both migrations would be performed. If the user is currently running version 1, only the latest migration will be performed.

Apply transformations

A final point to note is that Redux Persist supports the use of “transform functions”. These are added to your configuration and allow you to manipulate the data being saved or recovered.

The library’s documentation includes a number of popular transformations you can use. This allows you to automatically compress, encode, or expire your persistent state, without having to implement application-level logic yourself.

Transformations are specified as an array in your configuration object. They are executed in the order specified.

const persistStore = {
    key: "root",
    storage,
    transforms: [MyTransformer]
};

To write your own transformer, use the createTransform() function. This is passed two functions and a configuration object:

import {createTransform} from "redux-persist";
 
const MyTransformer = createTransform(
    (inboundState, key) => ({...inboundState, b64: btoa(inboundState.b64)}),
    (outboundState, key) => ({...outboundState, b64: atob(outboundState.b64)}),
    {}
);

In this example, we hit the b64 property of our state as its Base64 encoded value. When the data is kept in the storage (outboundState), the value is encrypted. It is decoded when the persistent state is hydrated (inboundState

The configuration object can be used to create a whitelist and blacklist of reducer names. The transformer would then only be used with adapters that meet these restrictions.

Conclusion

Redux Persist is a powerful library with a simple interface. You can set up automatic persistence of your Redux store in just a few lines of code. Users and developers alike will be grateful for the convenience.


Source link