react-native-onyx 2.0.136 → 2.0.138

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.
@@ -19,8 +19,8 @@ declare class OnyxCache {
19
19
  private recentKeys;
20
20
  /** A map of cached values */
21
21
  private storageMap;
22
- /** Index mapping collection keys to their member keys for O(1) lookup */
23
- private collectionIndex;
22
+ /** Cache of complete collection data objects for O(1) retrieval */
23
+ private collectionData;
24
24
  /**
25
25
  * Captured pending tasks for already running storage methods
26
26
  * Using a map yields better performance on operations such a delete
@@ -165,10 +165,6 @@ declare class OnyxCache {
165
165
  * Get all data for a collection key
166
166
  */
167
167
  getCollectionData(collectionKey: OnyxKey): Record<OnyxKey, OnyxValue<OnyxKey>> | undefined;
168
- /**
169
- * Get all member keys for a collection key
170
- */
171
- getCollectionMemberKeys(collectionKey: OnyxKey): Set<OnyxKey> | undefined;
172
168
  }
173
169
  declare const instance: OnyxCache;
174
170
  export default instance;
package/dist/OnyxCache.js CHANGED
@@ -68,10 +68,10 @@ class OnyxCache {
68
68
  this.nullishStorageKeys = new Set();
69
69
  this.recentKeys = new Set();
70
70
  this.storageMap = {};
71
- this.collectionIndex = {};
71
+ this.collectionData = {};
72
72
  this.pendingPromises = new Map();
73
73
  // bind all public methods to prevent problems with `this`
74
- (0, bindAll_1.default)(this, 'getAllKeys', 'get', 'hasCacheForKey', 'addKey', 'addNullishStorageKey', 'hasNullishStorageKey', 'clearNullishStorageKeys', 'set', 'drop', 'merge', 'hasPendingTask', 'getTaskPromise', 'captureTask', 'addToAccessedKeys', 'removeLeastRecentlyUsedKeys', 'setRecentKeysLimit', 'setAllKeys', 'setEvictionAllowList', 'getEvictionBlocklist', 'isEvictableKey', 'removeLastAccessedKey', 'addLastAccessedKey', 'addEvictableKeysToRecentlyAccessedList', 'getKeyForEviction', 'setCollectionKeys', 'isCollectionKey', 'getCollectionKey', 'getCollectionData', 'getCollectionMemberKeys');
74
+ (0, bindAll_1.default)(this, 'getAllKeys', 'get', 'hasCacheForKey', 'addKey', 'addNullishStorageKey', 'hasNullishStorageKey', 'clearNullishStorageKeys', 'set', 'drop', 'merge', 'hasPendingTask', 'getTaskPromise', 'captureTask', 'addToAccessedKeys', 'removeLeastRecentlyUsedKeys', 'setRecentKeysLimit', 'setAllKeys', 'setEvictionAllowList', 'getEvictionBlocklist', 'isEvictableKey', 'removeLastAccessedKey', 'addLastAccessedKey', 'addEvictableKeysToRecentlyAccessedList', 'getKeyForEviction', 'setCollectionKeys', 'isCollectionKey', 'getCollectionKey', 'getCollectionData');
75
75
  }
76
76
  /** Get all the storage keys */
77
77
  getAllKeys() {
@@ -136,33 +136,33 @@ class OnyxCache {
136
136
  const collectionKey = this.getCollectionKey(key);
137
137
  if (value === null || value === undefined) {
138
138
  delete this.storageMap[key];
139
- // Remove from collection index if it's a collection member
140
- if (collectionKey && this.getCollectionMemberKeys(collectionKey)) {
141
- this.collectionIndex[collectionKey].delete(key);
139
+ // Remove from collection data cache if it's a collection member
140
+ if (collectionKey && this.collectionData[collectionKey]) {
141
+ delete this.collectionData[collectionKey][key];
142
142
  }
143
143
  return undefined;
144
144
  }
145
145
  this.storageMap[key] = value;
146
- // Update collection index if this is a collection member
146
+ // Update collection data cache if this is a collection member
147
147
  if (collectionKey) {
148
- if (!this.getCollectionMemberKeys(collectionKey)) {
149
- this.collectionIndex[collectionKey] = new Set();
148
+ if (!this.collectionData[collectionKey]) {
149
+ this.collectionData[collectionKey] = {};
150
150
  }
151
- this.collectionIndex[collectionKey].add(key);
151
+ this.collectionData[collectionKey][key] = value;
152
152
  }
153
153
  return value;
154
154
  }
155
155
  /** Forget the cached value for the given key */
156
156
  drop(key) {
157
157
  delete this.storageMap[key];
158
- // Update collection index if this is a collection member
158
+ // Remove from collection data cache if this is a collection member
159
159
  const collectionKey = this.getCollectionKey(key);
160
- if (collectionKey && this.getCollectionMemberKeys(collectionKey)) {
161
- this.collectionIndex[collectionKey].delete(key);
160
+ if (collectionKey && this.collectionData[collectionKey]) {
161
+ delete this.collectionData[collectionKey][key];
162
162
  }
163
- // If this is a collection key, clear its index
163
+ // If this is a collection key, clear its data
164
164
  if (this.isCollectionKey(key)) {
165
- delete this.collectionIndex[key];
165
+ delete this.collectionData[key];
166
166
  }
167
167
  this.storageKeys.delete(key);
168
168
  this.recentKeys.delete(key);
@@ -185,19 +185,19 @@ class OnyxCache {
185
185
  const collectionKey = this.getCollectionKey(key);
186
186
  if (value === null || value === undefined) {
187
187
  this.addNullishStorageKey(key);
188
- // Remove from collection index if it's a collection member
189
- if (collectionKey && this.getCollectionMemberKeys(collectionKey)) {
190
- this.collectionIndex[collectionKey].delete(key);
188
+ // Remove from collection data cache if it's a collection member
189
+ if (collectionKey && this.collectionData[collectionKey]) {
190
+ delete this.collectionData[collectionKey][key];
191
191
  }
192
192
  }
193
193
  else {
194
194
  this.nullishStorageKeys.delete(key);
195
- // Update collection index if this is a collection member
195
+ // Update collection data cache if this is a collection member
196
196
  if (collectionKey) {
197
- if (!this.getCollectionMemberKeys(collectionKey)) {
198
- this.collectionIndex[collectionKey] = new Set();
197
+ if (!this.collectionData[collectionKey]) {
198
+ this.collectionData[collectionKey] = {};
199
199
  }
200
- this.collectionIndex[collectionKey].add(key);
200
+ this.collectionData[collectionKey][key] = this.storageMap[key];
201
201
  }
202
202
  }
203
203
  });
@@ -257,10 +257,10 @@ class OnyxCache {
257
257
  }
258
258
  for (const key of keysToRemove) {
259
259
  delete this.storageMap[key];
260
- // Update collection index if this is a collection member
260
+ // Remove from collection data cache if this is a collection member
261
261
  const collectionKey = this.getCollectionKey(key);
262
- if (collectionKey && this.getCollectionMemberKeys(collectionKey)) {
263
- this.collectionIndex[collectionKey].delete(key);
262
+ if (collectionKey && this.collectionData[collectionKey]) {
263
+ delete this.collectionData[collectionKey][key];
264
264
  }
265
265
  this.recentKeys.delete(key);
266
266
  }
@@ -358,12 +358,12 @@ class OnyxCache {
358
358
  */
359
359
  setCollectionKeys(collectionKeys) {
360
360
  this.collectionKeys = collectionKeys;
361
- // Initialize collection indexes for existing collection keys
361
+ // Initialize collection data for existing collection keys
362
362
  collectionKeys.forEach((collectionKey) => {
363
- if (this.getCollectionMemberKeys(collectionKey)) {
363
+ if (this.collectionData[collectionKey]) {
364
364
  return;
365
365
  }
366
- this.collectionIndex[collectionKey] = new Set();
366
+ this.collectionData[collectionKey] = {};
367
367
  });
368
368
  }
369
369
  /**
@@ -387,24 +387,12 @@ class OnyxCache {
387
387
  * Get all data for a collection key
388
388
  */
389
389
  getCollectionData(collectionKey) {
390
- const memberKeys = this.getCollectionMemberKeys(collectionKey);
391
- if (!memberKeys || memberKeys.size === 0) {
390
+ const cachedCollection = this.collectionData[collectionKey];
391
+ if (!cachedCollection || Object.keys(cachedCollection).length === 0) {
392
392
  return undefined;
393
393
  }
394
- const collectionData = {};
395
- memberKeys.forEach((memberKey) => {
396
- const value = this.storageMap[memberKey];
397
- if (value !== undefined) {
398
- collectionData[memberKey] = value;
399
- }
400
- });
401
- return collectionData;
402
- }
403
- /**
404
- * Get all member keys for a collection key
405
- */
406
- getCollectionMemberKeys(collectionKey) {
407
- return this.collectionIndex[collectionKey];
394
+ // Return a shallow copy to ensure React detects changes when items are added/removed
395
+ return Object.assign({}, cachedCollection);
408
396
  }
409
397
  }
410
398
  const instance = new OnyxCache();
@@ -143,14 +143,14 @@ declare function getCachedCollection<TKey extends CollectionKeyBase>(collectionK
143
143
  /**
144
144
  * When a collection of keys change, search for any callbacks matching the collection key and trigger those callbacks
145
145
  */
146
- declare function keysChanged<TKey extends CollectionKeyBase>(collectionKey: TKey, partialCollection: OnyxCollection<KeyValueMapping[TKey]>, partialPreviousCollection: OnyxCollection<KeyValueMapping[TKey]> | undefined, notifyConnectSubscribers?: boolean, notifyWithOnyxSubscribers?: boolean, notifyUseOnyxHookSubscribers?: boolean): void;
146
+ declare function keysChanged<TKey extends CollectionKeyBase>(collectionKey: TKey, partialCollection: OnyxCollection<KeyValueMapping[TKey]>, partialPreviousCollection: OnyxCollection<KeyValueMapping[TKey]> | undefined, notifyConnectSubscribers?: boolean, notifyWithOnyxSubscribers?: boolean): void;
147
147
  /**
148
148
  * When a key change happens, search for any callbacks matching the key or collection key and trigger those callbacks
149
149
  *
150
150
  * @example
151
151
  * keyChanged(key, value, subscriber => subscriber.initWithStoredValues === false)
152
152
  */
153
- declare function keyChanged<TKey extends OnyxKey>(key: TKey, value: OnyxValue<TKey>, previousValue: OnyxValue<TKey>, canUpdateSubscriber?: (subscriber?: Mapping<OnyxKey>) => boolean, notifyConnectSubscribers?: boolean, notifyWithOnyxSubscribers?: boolean, notifyUseOnyxHookSubscribers?: boolean): void;
153
+ declare function keyChanged<TKey extends OnyxKey>(key: TKey, value: OnyxValue<TKey>, previousValue: OnyxValue<TKey>, canUpdateSubscriber?: (subscriber?: Mapping<OnyxKey>) => boolean, notifyConnectSubscribers?: boolean, notifyWithOnyxSubscribers?: boolean): void;
154
154
  /**
155
155
  * Sends the data obtained from the keys to the connection. It either:
156
156
  * - sets state on the withOnyxInstances
package/dist/OnyxUtils.js CHANGED
@@ -440,25 +440,16 @@ function tryGetCachedValue(key, mapping) {
440
440
  let val = OnyxCache_1.default.get(key);
441
441
  if (isCollectionKey(key)) {
442
442
  const collectionData = OnyxCache_1.default.getCollectionData(key);
443
- const allCacheKeys = OnyxCache_1.default.getAllKeys();
444
- if (collectionData !== undefined && allCacheKeys.size > 0) {
443
+ if (collectionData !== undefined) {
445
444
  val = collectionData;
446
445
  }
447
446
  else {
448
- // Fallback to original logic
449
- // It is possible we haven't loaded all keys yet so we do not know if the
450
- // collection actually exists.
451
- if (allCacheKeys.size === 0) {
447
+ // If we haven't loaded all keys yet, we can't determine if the collection exists
448
+ if (OnyxCache_1.default.getAllKeys().size === 0) {
452
449
  return;
453
450
  }
454
- const values = {};
455
- allCacheKeys.forEach((cacheKey) => {
456
- if (!cacheKey.startsWith(key)) {
457
- return;
458
- }
459
- values[cacheKey] = OnyxCache_1.default.get(cacheKey);
460
- });
461
- val = values;
451
+ // Set an empty collection object for collections that exist but have no data
452
+ val = {};
462
453
  }
463
454
  }
464
455
  if (mapping === null || mapping === void 0 ? void 0 : mapping.selector) {
@@ -512,7 +503,7 @@ function getCachedCollection(collectionKey, collectionMemberKeys) {
512
503
  /**
513
504
  * When a collection of keys change, search for any callbacks matching the collection key and trigger those callbacks
514
505
  */
515
- function keysChanged(collectionKey, partialCollection, partialPreviousCollection, notifyConnectSubscribers = true, notifyWithOnyxSubscribers = true, notifyUseOnyxHookSubscribers = true) {
506
+ function keysChanged(collectionKey, partialCollection, partialPreviousCollection, notifyConnectSubscribers = true, notifyWithOnyxSubscribers = true) {
516
507
  // We prepare the "cached collection" which is the entire collection + the new partial data that
517
508
  // was merged in via mergeCollection().
518
509
  const cachedCollection = getCachedCollection(collectionKey);
@@ -540,8 +531,7 @@ function keysChanged(collectionKey, partialCollection, partialPreviousCollection
540
531
  const isSubscribedToCollectionMemberKey = isCollectionMemberKey(collectionKey, subscriber.key);
541
532
  // Regular Onyx.connect() subscriber found.
542
533
  if (typeof subscriber.callback === 'function') {
543
- // Check if it's a useOnyx or a regular Onyx.connect() subscriber
544
- if ((subscriber.isUseOnyxSubscriber && !notifyUseOnyxHookSubscribers) || (!subscriber.isUseOnyxSubscriber && !notifyConnectSubscribers)) {
534
+ if (!notifyConnectSubscribers) {
545
535
  continue;
546
536
  }
547
537
  // If they are subscribed to the collection key and using waitForCollectionCallback then we'll
@@ -671,7 +661,7 @@ function keysChanged(collectionKey, partialCollection, partialPreviousCollection
671
661
  * @example
672
662
  * keyChanged(key, value, subscriber => subscriber.initWithStoredValues === false)
673
663
  */
674
- function keyChanged(key, value, previousValue, canUpdateSubscriber = () => true, notifyConnectSubscribers = true, notifyWithOnyxSubscribers = true, notifyUseOnyxHookSubscribers = true) {
664
+ function keyChanged(key, value, previousValue, canUpdateSubscriber = () => true, notifyConnectSubscribers = true, notifyWithOnyxSubscribers = true) {
675
665
  var _a, _b;
676
666
  // Add or remove this key from the recentlyAccessedKeys lists
677
667
  if (value !== null) {
@@ -710,8 +700,7 @@ function keyChanged(key, value, previousValue, canUpdateSubscriber = () => true,
710
700
  }
711
701
  // Subscriber is a regular call to connect() and provided a callback
712
702
  if (typeof subscriber.callback === 'function') {
713
- // Check if it's a useOnyx or a regular Onyx.connect() subscriber
714
- if ((subscriber.isUseOnyxSubscriber && !notifyUseOnyxHookSubscribers) || (!subscriber.isUseOnyxSubscriber && !notifyConnectSubscribers)) {
703
+ if (!notifyConnectSubscribers) {
715
704
  continue;
716
705
  }
717
706
  if (lastConnectionCallbackData.has(subscriber.subscriptionID) && lastConnectionCallbackData.get(subscriber.subscriptionID) === value) {
@@ -891,8 +880,8 @@ function getCollectionDataAndSendAsObject(matchingKeys, mapping) {
891
880
  * scheduleSubscriberUpdate(key, value, subscriber => subscriber.initWithStoredValues === false)
892
881
  */
893
882
  function scheduleSubscriberUpdate(key, value, previousValue, canUpdateSubscriber = () => true) {
894
- const promise = Promise.resolve().then(() => keyChanged(key, value, previousValue, canUpdateSubscriber, true, false, false));
895
- batchUpdates(() => keyChanged(key, value, previousValue, canUpdateSubscriber, false, true, true));
883
+ const promise = Promise.resolve().then(() => keyChanged(key, value, previousValue, canUpdateSubscriber, true, false));
884
+ batchUpdates(() => keyChanged(key, value, previousValue, canUpdateSubscriber, false, true));
896
885
  return Promise.all([maybeFlushBatchUpdates(), promise]).then(() => undefined);
897
886
  }
898
887
  /**
@@ -901,8 +890,8 @@ function scheduleSubscriberUpdate(key, value, previousValue, canUpdateSubscriber
901
890
  * subscriber callbacks receive the data in a different format than they normally expect and it breaks code.
902
891
  */
903
892
  function scheduleNotifyCollectionSubscribers(key, value, previousValue) {
904
- const promise = Promise.resolve().then(() => keysChanged(key, value, previousValue, true, false, false));
905
- batchUpdates(() => keysChanged(key, value, previousValue, false, true, true));
893
+ const promise = Promise.resolve().then(() => keysChanged(key, value, previousValue, true, false));
894
+ batchUpdates(() => keysChanged(key, value, previousValue, false, true));
906
895
  return Promise.all([maybeFlushBatchUpdates(), promise]).then(() => undefined);
907
896
  }
908
897
  /**
package/dist/types.d.ts CHANGED
@@ -235,8 +235,6 @@ type BaseConnectOptions = {
235
235
  * with the same connect configurations.
236
236
  */
237
237
  reuseConnection?: boolean;
238
- /** Indicates whether this subscriber is created from the useOnyx hook. */
239
- isUseOnyxSubscriber?: boolean;
240
238
  };
241
239
  /** Represents the callback function used in `Onyx.connect()` method with a regular key. */
242
240
  type DefaultConnectCallback<TKey extends OnyxKey> = (value: OnyxEntry<KeyValueMapping[TKey]>, key: TKey) => void;
package/dist/useOnyx.js CHANGED
@@ -276,7 +276,6 @@ function useOnyx(key, options, dependencies = []) {
276
276
  initWithStoredValues: options === null || options === void 0 ? void 0 : options.initWithStoredValues,
277
277
  waitForCollectionCallback: OnyxUtils_1.default.isCollectionKey(key),
278
278
  reuseConnection: options === null || options === void 0 ? void 0 : options.reuseConnection,
279
- isUseOnyxSubscriber: true,
280
279
  });
281
280
  checkEvictableKey();
282
281
  return () => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-onyx",
3
- "version": "2.0.136",
3
+ "version": "2.0.138",
4
4
  "author": "Expensify, Inc.",
5
5
  "homepage": "https://expensify.com",
6
6
  "description": "State management for React Native",