zustand-sync-tabs
Version:
Zustand middleware to easily sync Zustand state between tabs and windows
93 lines (92 loc) • 3.86 kB
JavaScript
Object.defineProperty(exports, "__esModule", { value: true });
exports.syncTabs = void 0;
var LOAD = "__load__";
var syncTabs = function (f, options) { return function (set, get, store) {
/** avoid errors on server side or when BroadcastChannel is not supported */
if (!globalThis.BroadcastChannel) {
console.log("BroadcastChannel is not supported in this context!");
return f(set, get, store);
}
/** temporarily support `regExpToIgnore` */
if (!options.exclude)
options.exclude = [];
if (options.regExpToIgnore)
options.exclude.push(options.regExpToIgnore);
/** end of temporarily support `regExpToIgnore` */
var channel = new BroadcastChannel(options.name);
if (channel)
channel.postMessage(LOAD);
var set_ = function () {
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
var prevState = get();
set.apply(void 0, args);
var currentState = get();
var stateUpdates = {};
/** sync only updated state to avoid un-necessary re-renders */
var keysToSync = getKeysToSyncMemoised(Object.keys(currentState), options);
if (keysToSync.length === 0)
return;
keysToSync.forEach(function (k) {
if (currentState[k] !== prevState[k])
stateUpdates[k] = currentState[k];
});
if (Object.keys(stateUpdates).length) {
channel === null || channel === void 0 ? void 0 : channel.postMessage(stateUpdates);
}
};
if (channel)
channel.onmessage = function (e) {
if (e.data === LOAD) {
var currentState_1 = get();
var stateUpdates_1 = {};
/** sync only updated state to avoid un-necessary re-renders */
var keysToSync = getKeysToSyncMemoised(Object.keys(currentState_1), options);
if (keysToSync.length === 0)
return;
keysToSync.forEach(function (k) {
if (typeof currentState_1[k] !== "function") {
stateUpdates_1[k] = currentState_1[k];
}
});
if (Object.keys(stateUpdates_1).length) {
channel === null || channel === void 0 ? void 0 : channel.postMessage(stateUpdates_1);
}
}
else
set(e.data);
};
return f(set_, get, store);
}; };
exports.syncTabs = syncTabs;
function matchPatternOrKey(key, patterns) {
for (var _i = 0, patterns_1 = patterns; _i < patterns_1.length; _i++) {
var patternOrKey = patterns_1[_i];
if (typeof patternOrKey === "string" && key === patternOrKey)
return true;
else if (patternOrKey instanceof RegExp && patternOrKey.test(key))
return true;
}
return false;
}
/** Encapsulate cache in closure */
var getKeysToSyncMemoised = (function () {
var persistAndSyncKeysCache = {};
var getKeysSync = function (keys, options) {
var exclude = options.exclude, include = options.include;
var keysToInlcude = (include === null || include === void 0 ? void 0 : include.length)
? keys.filter(function (key) { return matchPatternOrKey(key, include); })
: keys;
var keysToPersistAndSync = keysToInlcude.filter(function (key) { return !matchPatternOrKey(key, exclude || []); });
return keysToPersistAndSync;
};
return function (keys, options) {
var cacheKey = JSON.stringify({ options: options, keys: keys });
if (!persistAndSyncKeysCache[cacheKey])
persistAndSyncKeysCache[cacheKey] = getKeysSync(keys, options);
return persistAndSyncKeysCache[cacheKey];
};
})();
;