redux-bind-selectors
Version:
A Redux store enhancer for computing derived state by binding selectors to the store
137 lines (105 loc) • 4.74 kB
JavaScript
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
typeof define === 'function' && define.amd ? define(factory) :
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.bindSelectors = factory());
})(this, (function () { 'use strict';
function ownKeys(object, enumerableOnly) {
var keys = Object.keys(object);
if (Object.getOwnPropertySymbols) {
var symbols = Object.getOwnPropertySymbols(object);
enumerableOnly && (symbols = symbols.filter(function (sym) {
return Object.getOwnPropertyDescriptor(object, sym).enumerable;
})), keys.push.apply(keys, symbols);
}
return keys;
}
function _objectSpread2(target) {
for (var i = 1; i < arguments.length; i++) {
var source = null != arguments[i] ? arguments[i] : {};
i % 2 ? ownKeys(Object(source), !0).forEach(function (key) {
_defineProperty(target, key, source[key]);
}) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) {
Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));
});
}
return target;
}
function _typeof(obj) {
"@babel/helpers - typeof";
return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (obj) {
return typeof obj;
} : function (obj) {
return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
}, _typeof(obj);
}
function _defineProperty(obj, key, value) {
if (key in obj) {
Object.defineProperty(obj, key, {
value: value,
enumerable: true,
configurable: true,
writable: true
});
} else {
obj[key] = value;
}
return obj;
}
/**
* Copyright (c) IBM Corp. 2017. All Rights Reserved.
* This project is licensed under the MIT License, see LICENSE.md
*/
/**
* A Redux Enhancer that intercepts the getState() method, runs selectors against the state,
* and merges the results back into a shallow clone of the state object, without polluting the original.
*/
function bindSelectors() {
var inputSelectorMap = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
// Check the validity of the selector map object
if (_typeof(inputSelectorMap) !== 'object') {
throw new Error('The selector map must be specified as an object');
}
var selectorMap = _objectSpread2({}, inputSelectorMap); // Check that all the selectors are functions
for (var key in selectorMap) {
if (typeof selectorMap[key] !== 'function') {
throw new Error("The selector '".concat(key, "' must be a function"));
}
}
return function (createStore) {
return function (reducer, preloadedState, enhancer) {
var store = createStore(reducer, preloadedState, enhancer); // Check the initial state
var lastStoreState = store.getState();
var stateType = _typeof(lastStoreState);
if (_typeof(lastStoreState) !== 'object') {
throw new Error("The state must be a JavaScript object, not a '".concat(stateType, "'"));
} // Check for duplicate keys between the selector map and the initial state
for (var _key in selectorMap) {
if (_key in lastStoreState) {
throw new Error("The selector key '".concat(_key, "' cannot be used because it exists in the initial state"));
}
}
var computedState;
var getState = function getState() {
var currentStoreState = store.getState(); // Only recalculate the state if the store state has changed, or we have not computed it before
if (currentStoreState !== lastStoreState || !computedState) {
lastStoreState = currentStoreState;
var derivedState = {};
for (var _key2 in selectorMap) {
derivedState[_key2] = selectorMap[_key2](currentStoreState);
if (typeof derivedState[_key2] === 'undefined') {
throw new Error("Selector '".concat(_key2, "' returned 'undefined'; to indicate no value, return 'null' instead"));
}
}
computedState = _objectSpread2(_objectSpread2({}, currentStoreState), derivedState);
}
return computedState;
};
return _objectSpread2(_objectSpread2({}, store), {}, {
getState: getState
});
};
};
}
return bindSelectors;
}));
//# sourceMappingURL=bind-selectors.js.map