react-native-onyx 2.0.138 → 2.0.139

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/dist/Onyx.js CHANGED
@@ -155,6 +155,13 @@ function disconnect(connection) {
155
155
  * @param options optional configuration object
156
156
  */
157
157
  function set(key, value, options) {
158
+ return setInternal(key, value, options);
159
+ }
160
+ /**
161
+ * @param isFromUpdate - Whether this call originates from Onyx.update()
162
+ * When isFromUpdate = true (called from Onyx.update()), useOnyx hook subscribers are batched to escape excessive re-renders in components
163
+ */
164
+ function setInternal(key, value, options, isFromUpdate = false) {
158
165
  // When we use Onyx.set to set a key we want to clear the current delta changes from Onyx.merge that were queued
159
166
  // before the value was set. If Onyx.merge is currently reading the old value from storage, it will then not apply the changes.
160
167
  if (OnyxUtils_1.default.hasPendingMergeForKey(key)) {
@@ -200,13 +207,13 @@ function set(key, value, options) {
200
207
  const hasChanged = (options === null || options === void 0 ? void 0 : options.skipCacheCheck) ? true : OnyxCache_1.default.hasValueChanged(key, valueWithoutNestedNullValues);
201
208
  OnyxUtils_1.default.logKeyChanged(OnyxUtils_1.default.METHOD.SET, key, value, hasChanged);
202
209
  // This approach prioritizes fast UI changes without waiting for data to be stored in device storage.
203
- const updatePromise = OnyxUtils_1.default.broadcastUpdate(key, valueWithoutNestedNullValues, hasChanged);
210
+ const updatePromise = OnyxUtils_1.default.broadcastUpdate(key, valueWithoutNestedNullValues, hasChanged, isFromUpdate);
204
211
  // If the value has not changed or the key got removed, calling Storage.setItem() would be redundant and a waste of performance, so return early instead.
205
212
  if (!hasChanged) {
206
213
  return updatePromise;
207
214
  }
208
215
  return storage_1.default.setItem(key, valueWithoutNestedNullValues)
209
- .catch((error) => OnyxUtils_1.default.evictStorageAndRetry(error, set, key, valueWithoutNestedNullValues))
216
+ .catch((error) => OnyxUtils_1.default.evictStorageAndRetry(error, setInternal, key, valueWithoutNestedNullValues, undefined, isFromUpdate))
210
217
  .then(() => {
211
218
  OnyxUtils_1.default.sendActionToDevTools(OnyxUtils_1.default.METHOD.SET, key, valueWithoutNestedNullValues);
212
219
  return updatePromise;
@@ -220,6 +227,13 @@ function set(key, value, options) {
220
227
  * @param data object keyed by ONYXKEYS and the values to set
221
228
  */
222
229
  function multiSet(data) {
230
+ return multiSetInternal(data);
231
+ }
232
+ /**
233
+ * @param isFromUpdate - Whether this call originates from Onyx.update()
234
+ * When isFromUpdate = true (called from Onyx.update()), useOnyx hook subscribers are batched to escape excessive re-renders in components
235
+ */
236
+ function multiSetInternal(data, isFromUpdate = false) {
223
237
  let newData = data;
224
238
  const skippableCollectionMemberIDs = OnyxUtils_1.default.getSkippableCollectionMemberIDs();
225
239
  if (skippableCollectionMemberIDs.size) {
@@ -248,10 +262,10 @@ function multiSet(data) {
248
262
  }
249
263
  // Update cache and optimistically inform subscribers on the next tick
250
264
  OnyxCache_1.default.set(key, value);
251
- return OnyxUtils_1.default.scheduleSubscriberUpdate(key, value, prevValue);
265
+ return OnyxUtils_1.default.scheduleSubscriberUpdate(key, value, prevValue, undefined, isFromUpdate);
252
266
  });
253
267
  return storage_1.default.multiSet(keyValuePairsToSet)
254
- .catch((error) => OnyxUtils_1.default.evictStorageAndRetry(error, multiSet, newData))
268
+ .catch((error) => OnyxUtils_1.default.evictStorageAndRetry(error, multiSetInternal, newData, isFromUpdate))
255
269
  .then(() => {
256
270
  OnyxUtils_1.default.sendActionToDevTools(OnyxUtils_1.default.METHOD.MULTI_SET, undefined, newData);
257
271
  return Promise.all(updatePromises);
@@ -275,6 +289,13 @@ function multiSet(data) {
275
289
  * Onyx.merge(ONYXKEYS.POLICY, {name: 'My Workspace'}); // -> {id: 1, name: 'My Workspace'}
276
290
  */
277
291
  function merge(key, changes) {
292
+ return mergeInternal(key, changes);
293
+ }
294
+ /**
295
+ * @param isFromUpdate - Whether this call originates from Onyx.update()
296
+ * When isFromUpdate = true (called from Onyx.update()), useOnyx hook subscribers are batched to escape excessive re-renders in components
297
+ */
298
+ function mergeInternal(key, changes, isFromUpdate = false) {
278
299
  const skippableCollectionMemberIDs = OnyxUtils_1.default.getSkippableCollectionMemberIDs();
279
300
  if (skippableCollectionMemberIDs.size) {
280
301
  try {
@@ -329,7 +350,7 @@ function merge(key, changes) {
329
350
  OnyxUtils_1.default.logKeyRemoved(OnyxUtils_1.default.METHOD.MERGE, key);
330
351
  return Promise.resolve();
331
352
  }
332
- return OnyxMerge_1.default.applyMerge(key, existingValue, validChanges).then(({ mergedValue, updatePromise }) => {
353
+ return OnyxMerge_1.default.applyMerge(key, existingValue, validChanges, isFromUpdate).then(({ mergedValue, updatePromise }) => {
333
354
  OnyxUtils_1.default.sendActionToDevTools(OnyxUtils_1.default.METHOD.MERGE, key, changes, mergedValue);
334
355
  return updatePromise;
335
356
  });
@@ -355,7 +376,14 @@ function merge(key, changes) {
355
376
  * @param collection Object collection keyed by individual collection member keys and values
356
377
  */
357
378
  function mergeCollection(collectionKey, collection) {
358
- return OnyxUtils_1.default.mergeCollectionWithPatches(collectionKey, collection);
379
+ return mergeCollectionInternal(collectionKey, collection);
380
+ }
381
+ /**
382
+ * @param isFromUpdate - Whether this call originates from Onyx.update()
383
+ * When isFromUpdate = true (called from Onyx.update()), useOnyx hook subscribers are batched to escape excessive re-renders in components
384
+ */
385
+ function mergeCollectionInternal(collectionKey, collection, isFromUpdate = false) {
386
+ return OnyxUtils_1.default.mergeCollectionWithPatches(collectionKey, collection, undefined, isFromUpdate);
359
387
  }
360
388
  /**
361
389
  * Clear out all the data in the store
@@ -435,10 +463,10 @@ function clear(keysToPreserve = []) {
435
463
  const updatePromises = [];
436
464
  // Notify the subscribers for each key/value group so they can receive the new values
437
465
  Object.entries(keyValuesToResetIndividually).forEach(([key, value]) => {
438
- updatePromises.push(OnyxUtils_1.default.scheduleSubscriberUpdate(key, value, OnyxCache_1.default.get(key, false)));
466
+ updatePromises.push(OnyxUtils_1.default.scheduleSubscriberUpdate(key, value, OnyxCache_1.default.get(key, false), undefined, false));
439
467
  });
440
468
  Object.entries(keyValuesToResetAsCollection).forEach(([key, value]) => {
441
- updatePromises.push(OnyxUtils_1.default.scheduleNotifyCollectionSubscribers(key, value));
469
+ updatePromises.push(OnyxUtils_1.default.scheduleNotifyCollectionSubscribers(key, value, undefined, false));
442
470
  });
443
471
  const defaultKeyValuePairs = Object.entries(Object.keys(defaultKeyStates)
444
472
  .filter((key) => !keysToPreserve.includes(key))
@@ -522,7 +550,7 @@ function update(data) {
522
550
  collectionKeys.forEach((collectionKey) => enqueueMergeOperation(collectionKey, mergedCollection[collectionKey]));
523
551
  }
524
552
  },
525
- [OnyxUtils_1.default.METHOD.SET_COLLECTION]: (k, v) => promises.push(() => setCollection(k, v)),
553
+ [OnyxUtils_1.default.METHOD.SET_COLLECTION]: (k, v) => promises.push(() => setCollectionInternal(k, v, true)),
526
554
  [OnyxUtils_1.default.METHOD.MULTI_SET]: (k, v) => Object.entries(v).forEach(([entryKey, entryValue]) => enqueueSetOperation(entryKey, entryValue)),
527
555
  [OnyxUtils_1.default.METHOD.CLEAR]: () => {
528
556
  clearPromise = clear();
@@ -564,23 +592,23 @@ function update(data) {
564
592
  set: {},
565
593
  });
566
594
  if (!utils_1.default.isEmptyObject(batchedCollectionUpdates.merge)) {
567
- promises.push(() => OnyxUtils_1.default.mergeCollectionWithPatches(collectionKey, batchedCollectionUpdates.merge, batchedCollectionUpdates.mergeReplaceNullPatches));
595
+ promises.push(() => OnyxUtils_1.default.mergeCollectionWithPatches(collectionKey, batchedCollectionUpdates.merge, batchedCollectionUpdates.mergeReplaceNullPatches, true));
568
596
  }
569
597
  if (!utils_1.default.isEmptyObject(batchedCollectionUpdates.set)) {
570
- promises.push(() => multiSet(batchedCollectionUpdates.set));
598
+ promises.push(() => multiSetInternal(batchedCollectionUpdates.set, true));
571
599
  }
572
600
  });
573
601
  Object.entries(updateQueue).forEach(([key, operations]) => {
574
602
  if (operations[0] === null) {
575
603
  const batchedChanges = OnyxUtils_1.default.mergeChanges(operations).result;
576
- promises.push(() => set(key, batchedChanges));
604
+ promises.push(() => setInternal(key, batchedChanges, undefined, true));
577
605
  return;
578
606
  }
579
607
  operations.forEach((operation) => {
580
- promises.push(() => merge(key, operation));
608
+ promises.push(() => mergeInternal(key, operation, true));
581
609
  });
582
610
  });
583
- const snapshotPromises = OnyxUtils_1.default.updateSnapshots(data, merge);
611
+ const snapshotPromises = OnyxUtils_1.default.updateSnapshots(data, (key, changes) => mergeInternal(key, changes, true));
584
612
  // We need to run the snapshot updates before the other updates so the snapshot data can be updated before the loading state in the snapshot
585
613
  const finalPromises = snapshotPromises.concat(promises);
586
614
  return clearPromise.then(() => Promise.all(finalPromises.map((p) => p()))).then(() => undefined);
@@ -599,6 +627,13 @@ function update(data) {
599
627
  * @param collection Object collection keyed by individual collection member keys and values
600
628
  */
601
629
  function setCollection(collectionKey, collection) {
630
+ return setCollectionInternal(collectionKey, collection);
631
+ }
632
+ /**
633
+ * @param isFromUpdate - Whether this call originates from Onyx.update()
634
+ * When isFromUpdate = true (called from Onyx.update()), useOnyx hook subscribers are batched to escape excessive re-renders in components
635
+ */
636
+ function setCollectionInternal(collectionKey, collection, isFromUpdate = false) {
602
637
  let resultCollection = collection;
603
638
  let resultCollectionKeys = Object.keys(resultCollection);
604
639
  // Confirm all the collection keys belong to the same parent
@@ -638,9 +673,9 @@ function setCollection(collectionKey, collection) {
638
673
  const keyValuePairs = OnyxUtils_1.default.prepareKeyValuePairsForStorage(mutableCollection, true);
639
674
  const previousCollection = OnyxUtils_1.default.getCachedCollection(collectionKey);
640
675
  keyValuePairs.forEach(([key, value]) => OnyxCache_1.default.set(key, value));
641
- const updatePromise = OnyxUtils_1.default.scheduleNotifyCollectionSubscribers(collectionKey, mutableCollection, previousCollection);
676
+ const updatePromise = OnyxUtils_1.default.scheduleNotifyCollectionSubscribers(collectionKey, mutableCollection, previousCollection, isFromUpdate);
642
677
  return storage_1.default.multiSet(keyValuePairs)
643
- .catch((error) => OnyxUtils_1.default.evictStorageAndRetry(error, setCollection, collectionKey, collection))
678
+ .catch((error) => OnyxUtils_1.default.evictStorageAndRetry(error, setCollectionInternal, collectionKey, collection, isFromUpdate))
644
679
  .then(() => {
645
680
  OnyxUtils_1.default.sendActionToDevTools(OnyxUtils_1.default.METHOD.SET_COLLECTION, undefined, mutableCollection);
646
681
  return updatePromise;
@@ -6,14 +6,14 @@ Object.defineProperty(exports, "__esModule", { value: true });
6
6
  const OnyxCache_1 = __importDefault(require("../OnyxCache"));
7
7
  const OnyxUtils_1 = __importDefault(require("../OnyxUtils"));
8
8
  const storage_1 = __importDefault(require("../storage"));
9
- const applyMerge = (key, existingValue, validChanges) => {
9
+ const applyMerge = (key, existingValue, validChanges, isFromUpdate = false) => {
10
10
  const { result: mergedValue } = OnyxUtils_1.default.mergeChanges(validChanges, existingValue);
11
11
  // In cache, we don't want to remove the key if it's null to improve performance and speed up the next merge.
12
12
  const hasChanged = OnyxCache_1.default.hasValueChanged(key, mergedValue);
13
13
  // Logging properties only since values could be sensitive things we don't want to log.
14
14
  OnyxUtils_1.default.logKeyChanged(OnyxUtils_1.default.METHOD.MERGE, key, mergedValue, hasChanged);
15
15
  // This approach prioritizes fast UI changes without waiting for data to be stored in device storage.
16
- const updatePromise = OnyxUtils_1.default.broadcastUpdate(key, mergedValue, hasChanged);
16
+ const updatePromise = OnyxUtils_1.default.broadcastUpdate(key, mergedValue, hasChanged, isFromUpdate);
17
17
  // If the value has not changed, calling Storage.setItem() would be redundant and a waste of performance, so return early instead.
18
18
  if (!hasChanged) {
19
19
  return Promise.resolve({ mergedValue, updatePromise });
@@ -6,7 +6,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
6
6
  const OnyxUtils_1 = __importDefault(require("../OnyxUtils"));
7
7
  const OnyxCache_1 = __importDefault(require("../OnyxCache"));
8
8
  const storage_1 = __importDefault(require("../storage"));
9
- const applyMerge = (key, existingValue, validChanges) => {
9
+ const applyMerge = (key, existingValue, validChanges, isFromUpdate = false) => {
10
10
  // If any of the changes is null, we need to discard the existing value.
11
11
  const baseValue = validChanges.includes(null) ? undefined : existingValue;
12
12
  // We first batch the changes into a single change with object removal marks,
@@ -19,7 +19,7 @@ const applyMerge = (key, existingValue, validChanges) => {
19
19
  // Logging properties only since values could be sensitive things we don't want to log.
20
20
  OnyxUtils_1.default.logKeyChanged(OnyxUtils_1.default.METHOD.MERGE, key, mergedValue, hasChanged);
21
21
  // This approach prioritizes fast UI changes without waiting for data to be stored in device storage.
22
- const updatePromise = OnyxUtils_1.default.broadcastUpdate(key, mergedValue, hasChanged);
22
+ const updatePromise = OnyxUtils_1.default.broadcastUpdate(key, mergedValue, hasChanged, isFromUpdate);
23
23
  // If the value has not changed, calling Storage.setItem() would be redundant and a waste of performance, so return early instead.
24
24
  if (!hasChanged) {
25
25
  return Promise.resolve({ mergedValue, updatePromise });
@@ -3,5 +3,5 @@ type ApplyMergeResult<TValue> = {
3
3
  mergedValue: TValue;
4
4
  updatePromise: Promise<void>;
5
5
  };
6
- type ApplyMerge = <TKey extends OnyxKey, TValue extends OnyxInput<OnyxKey> | undefined, TChange extends OnyxInput<OnyxKey> | null>(key: TKey, existingValue: TValue, validChanges: TChange[]) => Promise<ApplyMergeResult<TChange>>;
6
+ type ApplyMerge = <TKey extends OnyxKey, TValue extends OnyxInput<OnyxKey> | undefined, TChange extends OnyxInput<OnyxKey> | null>(key: TKey, existingValue: TValue, validChanges: TChange[], isFromUpdate?: boolean) => Promise<ApplyMergeResult<TChange>>;
7
7
  export type { ApplyMerge, ApplyMergeResult };
@@ -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): void;
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;
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): 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, notifyUseOnyxHookSubscribers?: 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
@@ -172,13 +172,13 @@ declare function getCollectionDataAndSendAsObject<TKey extends OnyxKey>(matching
172
172
  * @example
173
173
  * scheduleSubscriberUpdate(key, value, subscriber => subscriber.initWithStoredValues === false)
174
174
  */
175
- declare function scheduleSubscriberUpdate<TKey extends OnyxKey>(key: TKey, value: OnyxValue<TKey>, previousValue: OnyxValue<TKey>, canUpdateSubscriber?: (subscriber?: Mapping<OnyxKey>) => boolean): Promise<void>;
175
+ declare function scheduleSubscriberUpdate<TKey extends OnyxKey>(key: TKey, value: OnyxValue<TKey>, previousValue: OnyxValue<TKey>, canUpdateSubscriber?: (subscriber?: Mapping<OnyxKey>) => boolean, isFromUpdate?: boolean): Promise<void>;
176
176
  /**
177
177
  * This method is similar to notifySubscribersOnNextTick but it is built for working specifically with collections
178
178
  * so that keysChanged() is triggered for the collection and not keyChanged(). If this was not done, then the
179
179
  * subscriber callbacks receive the data in a different format than they normally expect and it breaks code.
180
180
  */
181
- declare function scheduleNotifyCollectionSubscribers<TKey extends OnyxKey>(key: TKey, value: OnyxCollection<KeyValueMapping[TKey]>, previousValue?: OnyxCollection<KeyValueMapping[TKey]>): Promise<void>;
181
+ declare function scheduleNotifyCollectionSubscribers<TKey extends OnyxKey>(key: TKey, value: OnyxCollection<KeyValueMapping[TKey]>, previousValue?: OnyxCollection<KeyValueMapping[TKey]>, isFromUpdate?: boolean): Promise<void>;
182
182
  /**
183
183
  * Remove a key from Onyx and update the subscribers
184
184
  */
@@ -193,7 +193,7 @@ declare function evictStorageAndRetry<TMethod extends typeof Onyx.set | typeof O
193
193
  /**
194
194
  * Notifies subscribers and writes current value to cache
195
195
  */
196
- declare function broadcastUpdate<TKey extends OnyxKey>(key: TKey, value: OnyxValue<TKey>, hasChanged?: boolean): Promise<void>;
196
+ declare function broadcastUpdate<TKey extends OnyxKey>(key: TKey, value: OnyxValue<TKey>, hasChanged?: boolean, isFromUpdate?: boolean): Promise<void>;
197
197
  declare function hasPendingMergeForKey(key: OnyxKey): boolean;
198
198
  /**
199
199
  * Storage expects array like: [["@MyApp_user", value_1], ["@MyApp_key", value_2]]
@@ -254,7 +254,7 @@ declare function updateSnapshots(data: OnyxUpdate[], mergeFn: typeof Onyx.merge)
254
254
  * @param mergeReplaceNullPatches Record where the key is a collection member key and the value is a list of
255
255
  * tuples that we'll use to replace the nested objects of that collection member record with something else.
256
256
  */
257
- declare function mergeCollectionWithPatches<TKey extends CollectionKeyBase, TMap>(collectionKey: TKey, collection: OnyxMergeCollectionInput<TKey, TMap>, mergeReplaceNullPatches?: MultiMergeReplaceNullPatches): Promise<void>;
257
+ declare function mergeCollectionWithPatches<TKey extends CollectionKeyBase, TMap>(collectionKey: TKey, collection: OnyxMergeCollectionInput<TKey, TMap>, mergeReplaceNullPatches?: MultiMergeReplaceNullPatches, isFromUpdate?: boolean): Promise<void>;
258
258
  declare function logKeyChanged(onyxMethod: Extract<OnyxMethod, 'set' | 'merge'>, key: OnyxKey, value: unknown, hasChanged: boolean): void;
259
259
  declare function logKeyRemoved(onyxMethod: Extract<OnyxMethod, 'set' | 'merge'>, key: OnyxKey): void;
260
260
  /**
package/dist/OnyxUtils.js CHANGED
@@ -503,7 +503,7 @@ function getCachedCollection(collectionKey, collectionMemberKeys) {
503
503
  /**
504
504
  * When a collection of keys change, search for any callbacks matching the collection key and trigger those callbacks
505
505
  */
506
- function keysChanged(collectionKey, partialCollection, partialPreviousCollection, notifyConnectSubscribers = true, notifyWithOnyxSubscribers = true) {
506
+ function keysChanged(collectionKey, partialCollection, partialPreviousCollection, notifyConnectSubscribers = true, notifyWithOnyxSubscribers = true, notifyUseOnyxHookSubscribers = true) {
507
507
  // We prepare the "cached collection" which is the entire collection + the new partial data that
508
508
  // was merged in via mergeCollection().
509
509
  const cachedCollection = getCachedCollection(collectionKey);
@@ -531,7 +531,8 @@ function keysChanged(collectionKey, partialCollection, partialPreviousCollection
531
531
  const isSubscribedToCollectionMemberKey = isCollectionMemberKey(collectionKey, subscriber.key);
532
532
  // Regular Onyx.connect() subscriber found.
533
533
  if (typeof subscriber.callback === 'function') {
534
- if (!notifyConnectSubscribers) {
534
+ // Check if it's a useOnyx or a regular Onyx.connect() subscriber
535
+ if ((subscriber.isUseOnyxSubscriber && !notifyUseOnyxHookSubscribers) || (!subscriber.isUseOnyxSubscriber && !notifyConnectSubscribers)) {
535
536
  continue;
536
537
  }
537
538
  // If they are subscribed to the collection key and using waitForCollectionCallback then we'll
@@ -661,7 +662,7 @@ function keysChanged(collectionKey, partialCollection, partialPreviousCollection
661
662
  * @example
662
663
  * keyChanged(key, value, subscriber => subscriber.initWithStoredValues === false)
663
664
  */
664
- function keyChanged(key, value, previousValue, canUpdateSubscriber = () => true, notifyConnectSubscribers = true, notifyWithOnyxSubscribers = true) {
665
+ function keyChanged(key, value, previousValue, canUpdateSubscriber = () => true, notifyConnectSubscribers = true, notifyWithOnyxSubscribers = true, notifyUseOnyxHookSubscribers = true) {
665
666
  var _a, _b;
666
667
  // Add or remove this key from the recentlyAccessedKeys lists
667
668
  if (value !== null) {
@@ -700,7 +701,8 @@ function keyChanged(key, value, previousValue, canUpdateSubscriber = () => true,
700
701
  }
701
702
  // Subscriber is a regular call to connect() and provided a callback
702
703
  if (typeof subscriber.callback === 'function') {
703
- if (!notifyConnectSubscribers) {
704
+ // Check if it's a useOnyx or a regular Onyx.connect() subscriber
705
+ if ((subscriber.isUseOnyxSubscriber && !notifyUseOnyxHookSubscribers) || (!subscriber.isUseOnyxSubscriber && !notifyConnectSubscribers)) {
704
706
  continue;
705
707
  }
706
708
  if (lastConnectionCallbackData.has(subscriber.subscriptionID) && lastConnectionCallbackData.get(subscriber.subscriptionID) === value) {
@@ -879,9 +881,9 @@ function getCollectionDataAndSendAsObject(matchingKeys, mapping) {
879
881
  * @example
880
882
  * scheduleSubscriberUpdate(key, value, subscriber => subscriber.initWithStoredValues === false)
881
883
  */
882
- function scheduleSubscriberUpdate(key, value, previousValue, canUpdateSubscriber = () => true) {
883
- const promise = Promise.resolve().then(() => keyChanged(key, value, previousValue, canUpdateSubscriber, true, false));
884
- batchUpdates(() => keyChanged(key, value, previousValue, canUpdateSubscriber, false, true));
884
+ function scheduleSubscriberUpdate(key, value, previousValue, canUpdateSubscriber = () => true, isFromUpdate = false) {
885
+ const promise = Promise.resolve().then(() => keyChanged(key, value, previousValue, canUpdateSubscriber, true, false, !isFromUpdate));
886
+ batchUpdates(() => keyChanged(key, value, previousValue, canUpdateSubscriber, false, true, isFromUpdate));
885
887
  return Promise.all([maybeFlushBatchUpdates(), promise]).then(() => undefined);
886
888
  }
887
889
  /**
@@ -889,9 +891,9 @@ function scheduleSubscriberUpdate(key, value, previousValue, canUpdateSubscriber
889
891
  * so that keysChanged() is triggered for the collection and not keyChanged(). If this was not done, then the
890
892
  * subscriber callbacks receive the data in a different format than they normally expect and it breaks code.
891
893
  */
892
- function scheduleNotifyCollectionSubscribers(key, value, previousValue) {
893
- const promise = Promise.resolve().then(() => keysChanged(key, value, previousValue, true, false));
894
- batchUpdates(() => keysChanged(key, value, previousValue, false, true));
894
+ function scheduleNotifyCollectionSubscribers(key, value, previousValue, isFromUpdate = false) {
895
+ const promise = Promise.resolve().then(() => keysChanged(key, value, previousValue, true, false, !isFromUpdate));
896
+ batchUpdates(() => keysChanged(key, value, previousValue, false, true, isFromUpdate));
895
897
  return Promise.all([maybeFlushBatchUpdates(), promise]).then(() => undefined);
896
898
  }
897
899
  /**
@@ -941,7 +943,7 @@ function evictStorageAndRetry(error, onyxMethod, ...args) {
941
943
  /**
942
944
  * Notifies subscribers and writes current value to cache
943
945
  */
944
- function broadcastUpdate(key, value, hasChanged) {
946
+ function broadcastUpdate(key, value, hasChanged, isFromUpdate = false) {
945
947
  const prevValue = OnyxCache_1.default.get(key, false);
946
948
  // Update subscribers if the cached value has changed, or when the subscriber specifically requires
947
949
  // all updates regardless of value changes (indicated by initWithStoredValues set to false).
@@ -951,7 +953,7 @@ function broadcastUpdate(key, value, hasChanged) {
951
953
  else {
952
954
  OnyxCache_1.default.addToAccessedKeys(key);
953
955
  }
954
- return scheduleSubscriberUpdate(key, value, prevValue, (subscriber) => hasChanged || (subscriber === null || subscriber === void 0 ? void 0 : subscriber.initWithStoredValues) === false).then(() => undefined);
956
+ return scheduleSubscriberUpdate(key, value, prevValue, (subscriber) => hasChanged || (subscriber === null || subscriber === void 0 ? void 0 : subscriber.initWithStoredValues) === false, isFromUpdate).then(() => undefined);
955
957
  }
956
958
  function hasPendingMergeForKey(key) {
957
959
  return !!mergeQueue[key];
@@ -1229,7 +1231,7 @@ function updateSnapshots(data, mergeFn) {
1229
1231
  * @param mergeReplaceNullPatches Record where the key is a collection member key and the value is a list of
1230
1232
  * tuples that we'll use to replace the nested objects of that collection member record with something else.
1231
1233
  */
1232
- function mergeCollectionWithPatches(collectionKey, collection, mergeReplaceNullPatches) {
1234
+ function mergeCollectionWithPatches(collectionKey, collection, mergeReplaceNullPatches, isFromUpdate = false) {
1233
1235
  if (!isValidNonEmptyCollectionForMerge(collection)) {
1234
1236
  Logger.logInfo('mergeCollection() called with invalid or empty value. Skipping this update.');
1235
1237
  return Promise.resolve();
@@ -1311,7 +1313,7 @@ function mergeCollectionWithPatches(collectionKey, collection, mergeReplaceNullP
1311
1313
  // and update all subscribers
1312
1314
  const promiseUpdate = previousCollectionPromise.then((previousCollection) => {
1313
1315
  OnyxCache_1.default.merge(finalMergedCollection);
1314
- return scheduleNotifyCollectionSubscribers(collectionKey, finalMergedCollection, previousCollection);
1316
+ return scheduleNotifyCollectionSubscribers(collectionKey, finalMergedCollection, previousCollection, isFromUpdate);
1315
1317
  });
1316
1318
  return Promise.all(promises)
1317
1319
  .catch((error) => evictStorageAndRetry(error, mergeCollectionWithPatches, collectionKey, resultCollection))
package/dist/types.d.ts CHANGED
@@ -235,6 +235,8 @@ 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;
238
240
  };
239
241
  /** Represents the callback function used in `Onyx.connect()` method with a regular key. */
240
242
  type DefaultConnectCallback<TKey extends OnyxKey> = (value: OnyxEntry<KeyValueMapping[TKey]>, key: TKey) => void;
package/dist/useOnyx.js CHANGED
@@ -276,6 +276,7 @@ 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,
279
280
  });
280
281
  checkEvictableKey();
281
282
  return () => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-onyx",
3
- "version": "2.0.138",
3
+ "version": "2.0.139",
4
4
  "author": "Expensify, Inc.",
5
5
  "homepage": "https://expensify.com",
6
6
  "description": "State management for React Native",