قالب وردپرس درنا توس
Home / Tips and Tricks / Syncing a Redux store between browser tabs – CloudSavvy IT

Syncing a Redux store between browser tabs – CloudSavvy IT



Illustration with the Redux logo

Redux is a useful way to manage status in complex web apps. However, your Redux store will not sync across different tabs, which can lead to tricky scenarios. If the user logs out in one tab, it would be ideal if that action is reflected in their other open tabs.

You can add sync between tabs using the react-state sync library. This provides middleware that automatically syncs the store across different tabs. You do not have to manually intervene in the synchronization process after the initial installation.

Overview

The Redux State Sync library provides a Redux middleware that you should add to your store. When the store receives an action, the middleware sends the same action in all other open tabs on your site.

Each tab sets up its own message listener to receive incoming action notifications. When the listener is notified, the action is sent to the tab̵

7;s storage.

Messages are exchanged between tabs using the Broadcast Channel API. This is a browser function that allows tabs of the same origin to communicate with each other. Tabs ‘subscribe’ to ‘channels’. They get a notification from the browser when another tab posts a subscriber channel.

Broadcast Channel is only available in newer browsers. Redux State Sync uses an abstraction that can fall back on alternative technologies. If Broadcast Channel is not supported, IndexedDB or LocalStorage is used instead.

Using Broadcast Channel puts some restrictions on what you can send between tabs. Data you send must be supported by the browser’s structured cloning algorithm. This includes scalars, arrays, plain JavaScript objects, and blobs. Complex values ​​are not transferred exactly.

Sync your store

To start using Redux State Sync, add it to your project via npm:

npm install redux-state-sync

Then create a basic store. We’ll tweak this code in a moment to add Redux State Sync.

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

Now we have a simple shop. To sync it between tabs, add the Redux State Sync middleware and set up a message listener.

import {createStore, applyMiddleware} from "redux";
import {createStateSyncMiddleware, initMessageListener} from "redux-state-sync";
 
const reduxStateSyncConfig = {};
 
const reducer = (state, action) => ({...state, ...action});
 
const store = createStore(
    reducer,
    state,
    applyMiddleware(createStateSyncMiddleware(reduxStateSyncConfig))
);
 
initMessageListener(store);

The store is now ready to use on different tabs. Open your site in two tabs. Submit an action on one of the tabs. You should see the action appear in both stores, effecting the corresponding status change in each. The Redux DevTools extension can be used to track incoming actions and the status changes they cause.

The state sync middleware is created using the createStateSyncMiddleware() utility function. This accepts a configuration object that is used to customize the behavior of Redux State Sync. We’ll take a closer look at this in the next section.

After the store is created, it will be passed to initMessageListener()This feature ensures that crosstab listening is configured. Without this call, tabs may not receive new actions if no action was sent on first load.

Using initMessageListener() does not give your tab access to the existing store on another tab. When the user opens a new tab, it has its own fresh food store by default. If you want new tabs to take their status of an open tab, use the initStateWithPrevTab() function instead.

const store = createStore(reducer, state, applyMiddleware(createStateSyncMiddleware({})));
initStateWithPrevTab(store);

The store’s status is replaced with the existing status if an open tab is still available.

Custom sync

Redux State Sync supports several configuration options that allow you to adjust the synchronization. Here are some of the most useful settings. Each is set as a property in the configuration object that is passed createStateSyncMiddleware()

Exclude Actions

Sometimes you have actions that you don’t want to sync. An example could be an action that causes a modal dialog to appear. Chances are you don’t want this dialog box to appear in all the user’s open tabs!

You can exclude specific named actions with the blacklist option. Pass a series of action names as the value.

const config = {
    blacklist: ["DEMO_ACTION"]
};
 
// ...
 
// This won't be synced to any other tabs
Store.dispatch({type: "DEMO_ACTION"});

You can also use a whitelist instead of a blacklist. Set the whitelist config option to allow only predefined actions to be synchronized.

Filter actions accurately

If neither blacklist or whitelist gives you enough control, set the predicate option. This accepts a function used to filter syncable actions.

const config = {
    predicate: action => (action.type !== "DEMO_ACTION")
};

The function is called every time a new action is received. It receives the action as a parameter. The function should return true or false to indicate whether the action should be synchronized with other tabs. In the example above, every action is synchronized except DEMO_ACTION

Broadcast Channel Settings

You can change the name of the broadcast channel by pressing the channel property. It is set to by default redux_state_syncNormally you don’t need to change this unless you want to have two separate sync routines.

You can pass options to the Broadcast Channel abstraction library by setting broadcastChannelOptionThis must be a configuration object accepted by the pubkey/broadcast-channel library.

You can use this to force the use of a particular storage technology. In this example, synchronization will always take place via IndexedDB, even if the browser has native support for Broadcast Channels.

const config = {
    broadcastChannelOption: {type: "idb"}
};

Integrate with Redux-Persist

You will often want to use Redux State Sync in conjunction with Redux Persist. Redux Persist is a popular library that automatically leaves your Redux store in the browser.

If you are using Redux Persist, you don’t need to use Redux Persist’s initStateWithPrevTab() position. Use initMessageListener() instead, since the initial state will always be the persistent state provided by Redux Persist.

Blacklist Redux Persist actions within your Redux State Sync configuration. These do not need to be synchronized across different tabs. Only sync changes that actually affect the store, rather than actions related to its lifecycle.

const config = {
    blacklist: ["persist/PERSIST", "persist/REHYDRATE"]
};

Resume

Redux State Sync allows you to sync user actions across different tabs. The applications are virtually limitless and are likely to improve the user experience. If users take actions on your site, they will immediately appear on their other open tabs.

The “classic” use case is to synchronize login and logout results. However, there are other benefits too, such as making incoming notifications available for all tabs or syncing client-side preferences such as the user-selected UI theme.

The scaled down redux state sync library weighs 19 KB. With an installation consisting of just a few extra lines of code, you should consider adding Redux State Sync to your next project. This allows you to link tabs together into a cohesive whole, instead of existing as independent entities.


Source link