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/lib/Onyx.js CHANGED
@@ -367,11 +367,15 @@ function keysChanged(collectionKey, partialCollection) {
367
367
  /**
368
368
  * When a key change happens, search for any callbacks matching the key or collection key and trigger those callbacks
369
369
  *
370
+ * @example
371
+ * keyChanged(key, value, subscriber => subscriber.initWithStoredValues === false)
372
+ *
370
373
  * @private
371
374
  * @param {String} key
372
375
  * @param {*} data
376
+ * @param {Function} [canUpdateSubscriber] only subscribers that pass this truth test will be updated
373
377
  */
374
- function keyChanged(key, data) {
378
+ function keyChanged(key, data, canUpdateSubscriber) {
375
379
  // Add or remove this key from the recentlyAccessedKeys lists
376
380
  if (!_.isNull(data)) {
377
381
  addLastAccessedKey(key);
@@ -385,7 +389,7 @@ function keyChanged(key, data) {
385
389
  const stateMappingKeys = _.keys(callbackToStateMapping);
386
390
  for (let i = 0; i < stateMappingKeys.length; i++) {
387
391
  const subscriber = callbackToStateMapping[stateMappingKeys[i]];
388
- if (!subscriber || !isKeyMatch(subscriber.key, key)) {
392
+ if (!subscriber || !isKeyMatch(subscriber.key, key) || (_.isFunction(canUpdateSubscriber) && !canUpdateSubscriber(subscriber))) {
389
393
  continue;
390
394
  }
391
395
 
@@ -631,12 +635,16 @@ function disconnect(connectionID, keyToRemoveFromEvictionBlocklist) {
631
635
  * 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
632
636
  * behavior just yet.
633
637
  *
638
+ * @example
639
+ * notifySubscribersOnNextTick(key, value, subscriber => subscriber.initWithStoredValues === false)
640
+ *
634
641
  * @param {String} key
635
642
  * @param {*} value
643
+ * @param {Function} [canUpdateSubscriber] only subscribers that pass this truth test will be updated
636
644
  */
637
645
  // eslint-disable-next-line rulesdir/no-negated-variables
638
- function notifySubscribersOnNextTick(key, value) {
639
- Promise.resolve().then(() => keyChanged(key, value));
646
+ function notifySubscribersOnNextTick(key, value, canUpdateSubscriber) {
647
+ Promise.resolve().then(() => keyChanged(key, value, canUpdateSubscriber));
640
648
  }
641
649
 
642
650
  /**
@@ -703,6 +711,14 @@ function set(key, value) {
703
711
  Logger.logAlert(`Onyx.set() called after Onyx.merge() for key: ${key}. It is recommended to use set() or merge() not both.`);
704
712
  }
705
713
 
714
+ // If the value in the cache is the same as what we have then do not update subscribers unless they
715
+ // have initWithStoredValues: false then they MUST get all updates even if nothing has changed.
716
+ if (!cache.hasValueChanged(key, value)) {
717
+ cache.addToAccessedKeys(key);
718
+ notifySubscribersOnNextTick(key, value, subscriber => subscriber.initWithStoredValues === false);
719
+ return Promise.resolve();
720
+ }
721
+
706
722
  // Adds the key to cache when it's not available
707
723
  cache.set(key, value);
708
724
  notifySubscribersOnNextTick(key, value);
@@ -1008,8 +1024,6 @@ function update(data) {
1008
1024
  * @param {Boolean} [options.captureMetrics] Enables Onyx benchmarking and exposes the get/print/reset functions
1009
1025
  * @param {Boolean} [options.shouldSyncMultipleInstances] Auto synchronize storage events between multiple instances
1010
1026
  * of Onyx running in different tabs/windows. Defaults to true for platforms that support local storage (web/desktop)
1011
- * @param {String[]} [option.keysToDisableSyncEvents=[]] Contains keys for which
1012
- * we want to disable sync event across tabs.
1013
1027
  * @param {Boolean} [options.debugSetState] Enables debugging setState() calls to connected components.
1014
1028
  * @example
1015
1029
  * Onyx.init({
@@ -1026,7 +1040,6 @@ function init({
1026
1040
  maxCachedKeysCount = 1000,
1027
1041
  captureMetrics = false,
1028
1042
  shouldSyncMultipleInstances = Boolean(global.localStorage),
1029
- keysToDisableSyncEvents = [],
1030
1043
  debugSetState = false,
1031
1044
  } = {}) {
1032
1045
  if (captureMetrics) {
@@ -1060,7 +1073,7 @@ function init({
1060
1073
  .then(deferredInitTask.resolve);
1061
1074
 
1062
1075
  if (shouldSyncMultipleInstances && _.isFunction(Storage.keepInstancesSync)) {
1063
- Storage.keepInstancesSync(keysToDisableSyncEvents, (key, value) => {
1076
+ Storage.keepInstancesSync((key, value) => {
1064
1077
  cache.set(key, value);
1065
1078
  keyChanged(key, value);
1066
1079
  });
package/lib/OnyxCache.js CHANGED
@@ -1,4 +1,5 @@
1
1
  import _ from 'underscore';
2
+ import {deepEqual} from 'fast-equals';
2
3
  import fastMerge from './fastMerge';
3
4
 
4
5
  const isDefined = _.negate(_.isUndefined);
@@ -191,6 +192,15 @@ class OnyxCache {
191
192
  setRecentKeysLimit(limit) {
192
193
  this.maxRecentKeysSize = limit;
193
194
  }
195
+
196
+ /**
197
+ * @param {String} key
198
+ * @param {*} value
199
+ * @returns {Boolean}
200
+ */
201
+ hasValueChanged(key, value) {
202
+ return !deepEqual(this.storageMap[key], value);
203
+ }
194
204
  }
195
205
 
196
206
  const instance = new OnyxCache();
@@ -16,12 +16,9 @@ const webStorage = {
16
16
  ...Storage,
17
17
 
18
18
  /**
19
- * Contains keys for which we want to disable sync event across tabs.
20
- * @param {String[]} keysToDisableSyncEvents
21
- * Storage synchronization mechanism keeping all opened tabs in sync
22
- * @param {function(key: String, data: *)} onStorageKeyChanged
19
+ * @param {Function} onStorageKeyChanged Storage synchronization mechanism keeping all opened tabs in sync
23
20
  */
24
- keepInstancesSync(keysToDisableSyncEvents, onStorageKeyChanged) {
21
+ keepInstancesSync(onStorageKeyChanged) {
25
22
  // Override set, remove and clear to raise storage events that we intercept in other tabs
26
23
  this.setItem = (key, value) => Storage.setItem(key, value)
27
24
  .then(() => raiseStorageSyncEvent(key));
@@ -43,10 +40,6 @@ const webStorage = {
43
40
  }
44
41
 
45
42
  const onyxKey = event.newValue;
46
- if (_.contains(keysToDisableSyncEvents, onyxKey)) {
47
- return;
48
- }
49
-
50
43
  Storage.getItem(onyxKey)
51
44
  .then(value => onStorageKeyChanged(onyxKey, value));
52
45
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-onyx",
3
- "version": "1.0.21",
3
+ "version": "1.0.23",
4
4
  "author": "Expensify, Inc.",
5
5
  "homepage": "https://expensify.com",
6
6
  "description": "State management for React Native",
@@ -40,6 +40,7 @@
40
40
  },
41
41
  "dependencies": {
42
42
  "ascii-table": "0.0.9",
43
+ "fast-equals": "^4.0.3",
43
44
  "lodash": "^4.17.21",
44
45
  "underscore": "^1.13.1"
45
46
  },