react-native-onyx 1.0.21 → 1.0.23

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/API.md CHANGED
@@ -13,7 +13,7 @@
13
13
  <dt><a href="#disconnect">disconnect(connectionID, [keyToRemoveFromEvictionBlocklist])</a></dt>
14
14
  <dd><p>Remove the listener for a react component</p>
15
15
  </dd>
16
- <dt><a href="#notifySubscribersOnNextTick">notifySubscribersOnNextTick(key, value)</a></dt>
16
+ <dt><a href="#notifySubscribersOnNextTick">notifySubscribersOnNextTick(key, value, [canUpdateSubscriber])</a></dt>
17
17
  <dd><p>This method mostly exists for historical reasons as this library was initially designed without a memory cache and one was added later.
18
18
  For this reason, Onyx works more similar to what you might expect from a native AsyncStorage with reads, writes, etc all becoming
19
19
  available async. Since we have code in our main applications that might expect things to work this way it&#39;s not safe to change this
@@ -115,7 +115,7 @@ Onyx.disconnect(connectionID);
115
115
  ```
116
116
  <a name="notifySubscribersOnNextTick"></a>
117
117
 
118
- ## notifySubscribersOnNextTick(key, value)
118
+ ## notifySubscribersOnNextTick(key, value, [canUpdateSubscriber])
119
119
  This method mostly exists for historical reasons as this library was initially designed without a memory cache and one was added later.
120
120
  For this reason, Onyx works more similar to what you might expect from a native AsyncStorage with reads, writes, etc all becoming
121
121
  available async. Since we have code in our main applications that might expect things to work this way it's not safe to change this
@@ -123,11 +123,16 @@ behavior just yet.
123
123
 
124
124
  **Kind**: global function
125
125
 
126
- | Param | Type |
127
- | --- | --- |
128
- | key | <code>String</code> |
129
- | value | <code>\*</code> |
126
+ | Param | Type | Description |
127
+ | --- | --- | --- |
128
+ | key | <code>String</code> | |
129
+ | value | <code>\*</code> | |
130
+ | [canUpdateSubscriber] | <code>function</code> | only subscribers that pass this truth test will be updated |
130
131
 
132
+ **Example**
133
+ ```js
134
+ notifySubscribersOnNextTick(key, value, subscriber => subscriber.initWithStoredValues === false)
135
+ ```
131
136
  <a name="set"></a>
132
137
 
133
138
  ## set(key, value) ⇒ <code>Promise</code>
@@ -251,7 +256,7 @@ Initialize the store with actions and listening for storage events
251
256
  | [options.maxCachedKeysCount] | <code>Number</code> | <code>55</code> | Sets how many recent keys should we try to keep in cache Setting this to 0 would practically mean no cache We try to free cache when we connect to a safe eviction key |
252
257
  | [options.captureMetrics] | <code>Boolean</code> | | Enables Onyx benchmarking and exposes the get/print/reset functions |
253
258
  | [options.shouldSyncMultipleInstances] | <code>Boolean</code> | | Auto synchronize storage events between multiple instances of Onyx running in different tabs/windows. Defaults to true for platforms that support local storage (web/desktop) |
254
- | [option.keysToDisableSyncEvents] | <code>Array.&lt;String&gt;</code> | <code>[]</code> | Contains keys for which we want to disable sync event across tabs. |
259
+ | [options.debugSetState] | <code>Boolean</code> | | Enables debugging setState() calls to connected components. |
255
260
 
256
261
  **Example**
257
262
  ```js
@@ -1,13 +1,13 @@
1
1
  (function webpackUniversalModuleDefinition(root, factory) {
2
2
  if(typeof exports === 'object' && typeof module === 'object')
3
- module.exports = factory(require("underscore"), require("expensify-common/lib/str"), require("lodash/get"), require("localforage"), require("lodash/transform"), require("react"));
3
+ module.exports = factory(require("underscore"), require("expensify-common/lib/str"), require("lodash/get"), require("localforage"), require("fast-equals"), require("lodash/transform"), require("react"));
4
4
  else if(typeof define === 'function' && define.amd)
5
- define(["underscore", "expensify-common/lib/str", "lodash/get", "localforage", "lodash/transform", "react"], factory);
5
+ define(["underscore", "expensify-common/lib/str", "lodash/get", "localforage", "fast-equals", "lodash/transform", "react"], factory);
6
6
  else if(typeof exports === 'object')
7
- exports["react-native-onyx/web"] = factory(require("underscore"), require("expensify-common/lib/str"), require("lodash/get"), require("localforage"), require("lodash/transform"), require("react"));
7
+ exports["react-native-onyx/web"] = factory(require("underscore"), require("expensify-common/lib/str"), require("lodash/get"), require("localforage"), require("fast-equals"), require("lodash/transform"), require("react"));
8
8
  else
9
- root["react-native-onyx/web"] = factory(root["underscore"], root["expensify-common/lib/str"], root["lodash/get"], root["localforage"], root["lodash/transform"], root["react"]);
10
- })(self, (__WEBPACK_EXTERNAL_MODULE_underscore__, __WEBPACK_EXTERNAL_MODULE_expensify_common_lib_str__, __WEBPACK_EXTERNAL_MODULE_lodash_get__, __WEBPACK_EXTERNAL_MODULE_localforage__, __WEBPACK_EXTERNAL_MODULE_lodash_transform__, __WEBPACK_EXTERNAL_MODULE_react__) => {
9
+ root["react-native-onyx/web"] = factory(root["underscore"], root["expensify-common/lib/str"], root["lodash/get"], root["localforage"], root["fast-equals"], root["lodash/transform"], root["react"]);
10
+ })(self, (__WEBPACK_EXTERNAL_MODULE_underscore__, __WEBPACK_EXTERNAL_MODULE_expensify_common_lib_str__, __WEBPACK_EXTERNAL_MODULE_lodash_get__, __WEBPACK_EXTERNAL_MODULE_localforage__, __WEBPACK_EXTERNAL_MODULE_fast_equals__, __WEBPACK_EXTERNAL_MODULE_lodash_transform__, __WEBPACK_EXTERNAL_MODULE_react__) => {
11
11
  return /******/ (() => { // webpackBootstrap
12
12
  /******/ var __webpack_modules__ = ({
13
13
 
@@ -858,11 +858,15 @@ function keysChanged(collectionKey, partialCollection) {
858
858
  /**
859
859
  * When a key change happens, search for any callbacks matching the key or collection key and trigger those callbacks
860
860
  *
861
+ * @example
862
+ * keyChanged(key, value, subscriber => subscriber.initWithStoredValues === false)
863
+ *
861
864
  * @private
862
865
  * @param {String} key
863
866
  * @param {*} data
867
+ * @param {Function} [canUpdateSubscriber] only subscribers that pass this truth test will be updated
864
868
  */
865
- function keyChanged(key, data) {
869
+ function keyChanged(key, data, canUpdateSubscriber) {
866
870
  // Add or remove this key from the recentlyAccessedKeys lists
867
871
  if (!_underscore.default.isNull(data)) {
868
872
  addLastAccessedKey(key);
@@ -876,7 +880,7 @@ function keyChanged(key, data) {
876
880
  var stateMappingKeys = _underscore.default.keys(callbackToStateMapping);var _loop2 = function _loop2(
877
881
  i) {
878
882
  var subscriber = callbackToStateMapping[stateMappingKeys[i]];
879
- if (!subscriber || !isKeyMatch(subscriber.key, key)) {
883
+ if (!subscriber || !isKeyMatch(subscriber.key, key) || _underscore.default.isFunction(canUpdateSubscriber) && !canUpdateSubscriber(subscriber)) {
880
884
  return "continue";
881
885
  }
882
886
 
@@ -1122,12 +1126,16 @@ function disconnect(connectionID, keyToRemoveFromEvictionBlocklist) {
1122
1126
  * available async. Since we have code in our main applications that might expect things to work this way it's not safe to change this
1123
1127
  * behavior just yet.
1124
1128
  *
1129
+ * @example
1130
+ * notifySubscribersOnNextTick(key, value, subscriber => subscriber.initWithStoredValues === false)
1131
+ *
1125
1132
  * @param {String} key
1126
1133
  * @param {*} value
1134
+ * @param {Function} [canUpdateSubscriber] only subscribers that pass this truth test will be updated
1127
1135
  */
1128
1136
  // eslint-disable-next-line rulesdir/no-negated-variables
1129
- function notifySubscribersOnNextTick(key, value) {
1130
- Promise.resolve().then(function () {return keyChanged(key, value);});
1137
+ function notifySubscribersOnNextTick(key, value, canUpdateSubscriber) {
1138
+ Promise.resolve().then(function () {return keyChanged(key, value, canUpdateSubscriber);});
1131
1139
  }
1132
1140
 
1133
1141
  /**
@@ -1194,6 +1202,14 @@ function set(key, value) {
1194
1202
  Logger.logAlert("Onyx.set() called after Onyx.merge() for key: " + key + ". It is recommended to use set() or merge() not both.");
1195
1203
  }
1196
1204
 
1205
+ // If the value in the cache is the same as what we have then do not update subscribers unless they
1206
+ // have initWithStoredValues: false then they MUST get all updates even if nothing has changed.
1207
+ if (!_OnyxCache.default.hasValueChanged(key, value)) {
1208
+ _OnyxCache.default.addToAccessedKeys(key);
1209
+ notifySubscribersOnNextTick(key, value, function (subscriber) {return subscriber.initWithStoredValues === false;});
1210
+ return Promise.resolve();
1211
+ }
1212
+
1197
1213
  // Adds the key to cache when it's not available
1198
1214
  _OnyxCache.default.set(key, value);
1199
1215
  notifySubscribersOnNextTick(key, value);
@@ -1499,8 +1515,6 @@ function update(data) {
1499
1515
  * @param {Boolean} [options.captureMetrics] Enables Onyx benchmarking and exposes the get/print/reset functions
1500
1516
  * @param {Boolean} [options.shouldSyncMultipleInstances] Auto synchronize storage events between multiple instances
1501
1517
  * of Onyx running in different tabs/windows. Defaults to true for platforms that support local storage (web/desktop)
1502
- * @param {String[]} [option.keysToDisableSyncEvents=[]] Contains keys for which
1503
- * we want to disable sync event across tabs.
1504
1518
  * @param {Boolean} [options.debugSetState] Enables debugging setState() calls to connected components.
1505
1519
  * @example
1506
1520
  * Onyx.init({
@@ -1518,8 +1532,7 @@ function init()
1518
1532
 
1519
1533
 
1520
1534
 
1521
-
1522
- {var _ref7 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},_ref7$keys = _ref7.keys,keys = _ref7$keys === void 0 ? {} : _ref7$keys,_ref7$initialKeyState = _ref7.initialKeyStates,initialKeyStates = _ref7$initialKeyState === void 0 ? {} : _ref7$initialKeyState,_ref7$safeEvictionKey = _ref7.safeEvictionKeys,safeEvictionKeys = _ref7$safeEvictionKey === void 0 ? [] : _ref7$safeEvictionKey,_ref7$maxCachedKeysCo = _ref7.maxCachedKeysCount,maxCachedKeysCount = _ref7$maxCachedKeysCo === void 0 ? 1000 : _ref7$maxCachedKeysCo,_ref7$captureMetrics = _ref7.captureMetrics,captureMetrics = _ref7$captureMetrics === void 0 ? false : _ref7$captureMetrics,_ref7$shouldSyncMulti = _ref7.shouldSyncMultipleInstances,shouldSyncMultipleInstances = _ref7$shouldSyncMulti === void 0 ? Boolean(__webpack_require__.g.localStorage) : _ref7$shouldSyncMulti,_ref7$keysToDisableSy = _ref7.keysToDisableSyncEvents,keysToDisableSyncEvents = _ref7$keysToDisableSy === void 0 ? [] : _ref7$keysToDisableSy,_ref7$debugSetState = _ref7.debugSetState,debugSetState = _ref7$debugSetState === void 0 ? false : _ref7$debugSetState;
1535
+ {var _ref7 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},_ref7$keys = _ref7.keys,keys = _ref7$keys === void 0 ? {} : _ref7$keys,_ref7$initialKeyState = _ref7.initialKeyStates,initialKeyStates = _ref7$initialKeyState === void 0 ? {} : _ref7$initialKeyState,_ref7$safeEvictionKey = _ref7.safeEvictionKeys,safeEvictionKeys = _ref7$safeEvictionKey === void 0 ? [] : _ref7$safeEvictionKey,_ref7$maxCachedKeysCo = _ref7.maxCachedKeysCount,maxCachedKeysCount = _ref7$maxCachedKeysCo === void 0 ? 1000 : _ref7$maxCachedKeysCo,_ref7$captureMetrics = _ref7.captureMetrics,captureMetrics = _ref7$captureMetrics === void 0 ? false : _ref7$captureMetrics,_ref7$shouldSyncMulti = _ref7.shouldSyncMultipleInstances,shouldSyncMultipleInstances = _ref7$shouldSyncMulti === void 0 ? Boolean(__webpack_require__.g.localStorage) : _ref7$shouldSyncMulti,_ref7$debugSetState = _ref7.debugSetState,debugSetState = _ref7$debugSetState === void 0 ? false : _ref7$debugSetState;
1523
1536
  if (captureMetrics) {
1524
1537
  // The code here is only bundled and applied when the captureMetrics is set
1525
1538
  // eslint-disable-next-line no-use-before-define
@@ -1551,7 +1564,7 @@ function init()
1551
1564
  then(deferredInitTask.resolve);
1552
1565
 
1553
1566
  if (shouldSyncMultipleInstances && _underscore.default.isFunction(_storage.default.keepInstancesSync)) {
1554
- _storage.default.keepInstancesSync(keysToDisableSyncEvents, function (key, value) {
1567
+ _storage.default.keepInstancesSync(function (key, value) {
1555
1568
  _OnyxCache.default.set(key, value);
1556
1569
  keyChanged(key, value);
1557
1570
  });
@@ -1623,6 +1636,7 @@ Onyx;exports["default"] = _default;
1623
1636
  /***/ ((__unused_webpack_module, exports, __webpack_require__) => {
1624
1637
 
1625
1638
  var _interopRequireDefault = __webpack_require__(/*! @babel/runtime/helpers/interopRequireDefault */ "./node_modules/@babel/runtime/helpers/interopRequireDefault.js");Object.defineProperty(exports, "__esModule", ({ value: true }));exports["default"] = void 0;var _toConsumableArray2 = _interopRequireDefault(__webpack_require__(/*! @babel/runtime/helpers/toConsumableArray */ "./node_modules/@babel/runtime/helpers/toConsumableArray.js"));var _extends2 = _interopRequireDefault(__webpack_require__(/*! @babel/runtime/helpers/extends */ "./node_modules/@babel/runtime/helpers/extends.js"));var _classCallCheck2 = _interopRequireDefault(__webpack_require__(/*! @babel/runtime/helpers/classCallCheck */ "./node_modules/@babel/runtime/helpers/classCallCheck.js"));var _createClass2 = _interopRequireDefault(__webpack_require__(/*! @babel/runtime/helpers/createClass */ "./node_modules/@babel/runtime/helpers/createClass.js"));var _underscore = _interopRequireDefault(__webpack_require__(/*! underscore */ "underscore"));
1639
+ var _fastEquals = __webpack_require__(/*! fast-equals */ "fast-equals");
1626
1640
  var _fastMerge = _interopRequireDefault(__webpack_require__(/*! ./fastMerge */ "./lib/fastMerge.js"));
1627
1641
 
1628
1642
  var isDefined = _underscore.default.negate(_underscore.default.isUndefined);
@@ -1814,6 +1828,15 @@ OnyxCache = /*#__PURE__*/function () {
1814
1828
  */ }, { key: "setRecentKeysLimit", value: function setRecentKeysLimit(
1815
1829
  limit) {
1816
1830
  this.maxRecentKeysSize = limit;
1831
+ }
1832
+
1833
+ /**
1834
+ * @param {String} key
1835
+ * @param {*} value
1836
+ * @returns {Boolean}
1837
+ */ }, { key: "hasValueChanged", value: function hasValueChanged(
1838
+ key, value) {
1839
+ return !(0, _fastEquals.deepEqual)(this.storageMap[key], value);
1817
1840
  } }]);return OnyxCache;}();
1818
1841
 
1819
1842
 
@@ -2093,12 +2116,9 @@ var webStorage = (0, _extends2.default)({},
2093
2116
  _LocalForage.default, {
2094
2117
 
2095
2118
  /**
2096
- * Contains keys for which we want to disable sync event across tabs.
2097
- * @param {String[]} keysToDisableSyncEvents
2098
- * Storage synchronization mechanism keeping all opened tabs in sync
2099
- * @param {function(key: String, data: *)} onStorageKeyChanged
2119
+ * @param {Function} onStorageKeyChanged Storage synchronization mechanism keeping all opened tabs in sync
2100
2120
  */
2101
- keepInstancesSync: function keepInstancesSync(keysToDisableSyncEvents, onStorageKeyChanged) {var _this = this;
2121
+ keepInstancesSync: function keepInstancesSync(onStorageKeyChanged) {var _this = this;
2102
2122
  // Override set, remove and clear to raise storage events that we intercept in other tabs
2103
2123
  this.setItem = function (key, value) {return _LocalForage.default.setItem(key, value).
2104
2124
  then(function () {return raiseStorageSyncEvent(key);});};
@@ -2120,10 +2140,6 @@ _LocalForage.default, {
2120
2140
  }
2121
2141
 
2122
2142
  var onyxKey = event.newValue;
2123
- if (_underscore.default.contains(keysToDisableSyncEvents, onyxKey)) {
2124
- return;
2125
- }
2126
-
2127
2143
  _LocalForage.default.getItem(onyxKey).
2128
2144
  then(function (value) {return onStorageKeyChanged(onyxKey, value);});
2129
2145
  });
@@ -3562,6 +3578,17 @@ module.exports = __WEBPACK_EXTERNAL_MODULE_expensify_common_lib_str__;
3562
3578
 
3563
3579
  /***/ }),
3564
3580
 
3581
+ /***/ "fast-equals":
3582
+ /*!******************************!*\
3583
+ !*** external "fast-equals" ***!
3584
+ \******************************/
3585
+ /***/ ((module) => {
3586
+
3587
+ "use strict";
3588
+ module.exports = __WEBPACK_EXTERNAL_MODULE_fast_equals__;
3589
+
3590
+ /***/ }),
3591
+
3565
3592
  /***/ "localforage":
3566
3593
  /*!******************************!*\
3567
3594
  !*** external "localforage" ***!