react-native-onyx 2.0.139 → 2.0.141

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,13 +155,6 @@ 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) {
165
158
  // When we use Onyx.set to set a key we want to clear the current delta changes from Onyx.merge that were queued
166
159
  // before the value was set. If Onyx.merge is currently reading the old value from storage, it will then not apply the changes.
167
160
  if (OnyxUtils_1.default.hasPendingMergeForKey(key)) {
@@ -207,13 +200,13 @@ function setInternal(key, value, options, isFromUpdate = false) {
207
200
  const hasChanged = (options === null || options === void 0 ? void 0 : options.skipCacheCheck) ? true : OnyxCache_1.default.hasValueChanged(key, valueWithoutNestedNullValues);
208
201
  OnyxUtils_1.default.logKeyChanged(OnyxUtils_1.default.METHOD.SET, key, value, hasChanged);
209
202
  // This approach prioritizes fast UI changes without waiting for data to be stored in device storage.
210
- const updatePromise = OnyxUtils_1.default.broadcastUpdate(key, valueWithoutNestedNullValues, hasChanged, isFromUpdate);
203
+ const updatePromise = OnyxUtils_1.default.broadcastUpdate(key, valueWithoutNestedNullValues, hasChanged);
211
204
  // 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.
212
205
  if (!hasChanged) {
213
206
  return updatePromise;
214
207
  }
215
208
  return storage_1.default.setItem(key, valueWithoutNestedNullValues)
216
- .catch((error) => OnyxUtils_1.default.evictStorageAndRetry(error, setInternal, key, valueWithoutNestedNullValues, undefined, isFromUpdate))
209
+ .catch((error) => OnyxUtils_1.default.evictStorageAndRetry(error, set, key, valueWithoutNestedNullValues))
217
210
  .then(() => {
218
211
  OnyxUtils_1.default.sendActionToDevTools(OnyxUtils_1.default.METHOD.SET, key, valueWithoutNestedNullValues);
219
212
  return updatePromise;
@@ -227,13 +220,6 @@ function setInternal(key, value, options, isFromUpdate = false) {
227
220
  * @param data object keyed by ONYXKEYS and the values to set
228
221
  */
229
222
  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) {
237
223
  let newData = data;
238
224
  const skippableCollectionMemberIDs = OnyxUtils_1.default.getSkippableCollectionMemberIDs();
239
225
  if (skippableCollectionMemberIDs.size) {
@@ -262,10 +248,10 @@ function multiSetInternal(data, isFromUpdate = false) {
262
248
  }
263
249
  // Update cache and optimistically inform subscribers on the next tick
264
250
  OnyxCache_1.default.set(key, value);
265
- return OnyxUtils_1.default.scheduleSubscriberUpdate(key, value, prevValue, undefined, isFromUpdate);
251
+ return OnyxUtils_1.default.scheduleSubscriberUpdate(key, value, prevValue);
266
252
  });
267
253
  return storage_1.default.multiSet(keyValuePairsToSet)
268
- .catch((error) => OnyxUtils_1.default.evictStorageAndRetry(error, multiSetInternal, newData, isFromUpdate))
254
+ .catch((error) => OnyxUtils_1.default.evictStorageAndRetry(error, multiSet, newData))
269
255
  .then(() => {
270
256
  OnyxUtils_1.default.sendActionToDevTools(OnyxUtils_1.default.METHOD.MULTI_SET, undefined, newData);
271
257
  return Promise.all(updatePromises);
@@ -289,13 +275,6 @@ function multiSetInternal(data, isFromUpdate = false) {
289
275
  * Onyx.merge(ONYXKEYS.POLICY, {name: 'My Workspace'}); // -> {id: 1, name: 'My Workspace'}
290
276
  */
291
277
  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) {
299
278
  const skippableCollectionMemberIDs = OnyxUtils_1.default.getSkippableCollectionMemberIDs();
300
279
  if (skippableCollectionMemberIDs.size) {
301
280
  try {
@@ -350,7 +329,7 @@ function mergeInternal(key, changes, isFromUpdate = false) {
350
329
  OnyxUtils_1.default.logKeyRemoved(OnyxUtils_1.default.METHOD.MERGE, key);
351
330
  return Promise.resolve();
352
331
  }
353
- return OnyxMerge_1.default.applyMerge(key, existingValue, validChanges, isFromUpdate).then(({ mergedValue, updatePromise }) => {
332
+ return OnyxMerge_1.default.applyMerge(key, existingValue, validChanges).then(({ mergedValue, updatePromise }) => {
354
333
  OnyxUtils_1.default.sendActionToDevTools(OnyxUtils_1.default.METHOD.MERGE, key, changes, mergedValue);
355
334
  return updatePromise;
356
335
  });
@@ -376,14 +355,7 @@ function mergeInternal(key, changes, isFromUpdate = false) {
376
355
  * @param collection Object collection keyed by individual collection member keys and values
377
356
  */
378
357
  function mergeCollection(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);
358
+ return OnyxUtils_1.default.mergeCollectionWithPatches(collectionKey, collection);
387
359
  }
388
360
  /**
389
361
  * Clear out all the data in the store
@@ -463,10 +435,10 @@ function clear(keysToPreserve = []) {
463
435
  const updatePromises = [];
464
436
  // Notify the subscribers for each key/value group so they can receive the new values
465
437
  Object.entries(keyValuesToResetIndividually).forEach(([key, value]) => {
466
- updatePromises.push(OnyxUtils_1.default.scheduleSubscriberUpdate(key, value, OnyxCache_1.default.get(key, false), undefined, false));
438
+ updatePromises.push(OnyxUtils_1.default.scheduleSubscriberUpdate(key, value, OnyxCache_1.default.get(key, false)));
467
439
  });
468
440
  Object.entries(keyValuesToResetAsCollection).forEach(([key, value]) => {
469
- updatePromises.push(OnyxUtils_1.default.scheduleNotifyCollectionSubscribers(key, value, undefined, false));
441
+ updatePromises.push(OnyxUtils_1.default.scheduleNotifyCollectionSubscribers(key, value));
470
442
  });
471
443
  const defaultKeyValuePairs = Object.entries(Object.keys(defaultKeyStates)
472
444
  .filter((key) => !keysToPreserve.includes(key))
@@ -550,7 +522,7 @@ function update(data) {
550
522
  collectionKeys.forEach((collectionKey) => enqueueMergeOperation(collectionKey, mergedCollection[collectionKey]));
551
523
  }
552
524
  },
553
- [OnyxUtils_1.default.METHOD.SET_COLLECTION]: (k, v) => promises.push(() => setCollectionInternal(k, v, true)),
525
+ [OnyxUtils_1.default.METHOD.SET_COLLECTION]: (k, v) => promises.push(() => setCollection(k, v)),
554
526
  [OnyxUtils_1.default.METHOD.MULTI_SET]: (k, v) => Object.entries(v).forEach(([entryKey, entryValue]) => enqueueSetOperation(entryKey, entryValue)),
555
527
  [OnyxUtils_1.default.METHOD.CLEAR]: () => {
556
528
  clearPromise = clear();
@@ -592,23 +564,23 @@ function update(data) {
592
564
  set: {},
593
565
  });
594
566
  if (!utils_1.default.isEmptyObject(batchedCollectionUpdates.merge)) {
595
- promises.push(() => OnyxUtils_1.default.mergeCollectionWithPatches(collectionKey, batchedCollectionUpdates.merge, batchedCollectionUpdates.mergeReplaceNullPatches, true));
567
+ promises.push(() => OnyxUtils_1.default.mergeCollectionWithPatches(collectionKey, batchedCollectionUpdates.merge, batchedCollectionUpdates.mergeReplaceNullPatches));
596
568
  }
597
569
  if (!utils_1.default.isEmptyObject(batchedCollectionUpdates.set)) {
598
- promises.push(() => multiSetInternal(batchedCollectionUpdates.set, true));
570
+ promises.push(() => OnyxUtils_1.default.partialSetCollection(collectionKey, batchedCollectionUpdates.set));
599
571
  }
600
572
  });
601
573
  Object.entries(updateQueue).forEach(([key, operations]) => {
602
574
  if (operations[0] === null) {
603
575
  const batchedChanges = OnyxUtils_1.default.mergeChanges(operations).result;
604
- promises.push(() => setInternal(key, batchedChanges, undefined, true));
576
+ promises.push(() => set(key, batchedChanges));
605
577
  return;
606
578
  }
607
579
  operations.forEach((operation) => {
608
- promises.push(() => mergeInternal(key, operation, true));
580
+ promises.push(() => merge(key, operation));
609
581
  });
610
582
  });
611
- const snapshotPromises = OnyxUtils_1.default.updateSnapshots(data, (key, changes) => mergeInternal(key, changes, true));
583
+ const snapshotPromises = OnyxUtils_1.default.updateSnapshots(data, merge);
612
584
  // 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
613
585
  const finalPromises = snapshotPromises.concat(promises);
614
586
  return clearPromise.then(() => Promise.all(finalPromises.map((p) => p()))).then(() => undefined);
@@ -627,13 +599,6 @@ function update(data) {
627
599
  * @param collection Object collection keyed by individual collection member keys and values
628
600
  */
629
601
  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) {
637
602
  let resultCollection = collection;
638
603
  let resultCollectionKeys = Object.keys(resultCollection);
639
604
  // Confirm all the collection keys belong to the same parent
@@ -673,9 +638,9 @@ function setCollectionInternal(collectionKey, collection, isFromUpdate = false)
673
638
  const keyValuePairs = OnyxUtils_1.default.prepareKeyValuePairsForStorage(mutableCollection, true);
674
639
  const previousCollection = OnyxUtils_1.default.getCachedCollection(collectionKey);
675
640
  keyValuePairs.forEach(([key, value]) => OnyxCache_1.default.set(key, value));
676
- const updatePromise = OnyxUtils_1.default.scheduleNotifyCollectionSubscribers(collectionKey, mutableCollection, previousCollection, isFromUpdate);
641
+ const updatePromise = OnyxUtils_1.default.scheduleNotifyCollectionSubscribers(collectionKey, mutableCollection, previousCollection);
677
642
  return storage_1.default.multiSet(keyValuePairs)
678
- .catch((error) => OnyxUtils_1.default.evictStorageAndRetry(error, setCollectionInternal, collectionKey, collection, isFromUpdate))
643
+ .catch((error) => OnyxUtils_1.default.evictStorageAndRetry(error, setCollection, collectionKey, collection))
679
644
  .then(() => {
680
645
  OnyxUtils_1.default.sendActionToDevTools(OnyxUtils_1.default.METHOD.SET_COLLECTION, undefined, mutableCollection);
681
646
  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, isFromUpdate = false) => {
9
+ const applyMerge = (key, existingValue, validChanges) => {
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, isFromUpdate);
16
+ const updatePromise = OnyxUtils_1.default.broadcastUpdate(key, mergedValue, hasChanged);
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, isFromUpdate = false) => {
9
+ const applyMerge = (key, existingValue, validChanges) => {
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, isFromUpdate = false) => {
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, isFromUpdate);
22
+ const updatePromise = OnyxUtils_1.default.broadcastUpdate(key, mergedValue, hasChanged);
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[], isFromUpdate?: boolean) => 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[]) => 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, 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
@@ -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, isFromUpdate?: boolean): Promise<void>;
175
+ declare function scheduleSubscriberUpdate<TKey extends OnyxKey>(key: TKey, value: OnyxValue<TKey>, previousValue: OnyxValue<TKey>, canUpdateSubscriber?: (subscriber?: Mapping<OnyxKey>) => 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]>, isFromUpdate?: boolean): Promise<void>;
181
+ declare function scheduleNotifyCollectionSubscribers<TKey extends OnyxKey>(key: TKey, value: OnyxCollection<KeyValueMapping[TKey]>, previousValue?: OnyxCollection<KeyValueMapping[TKey]>): 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, isFromUpdate?: boolean): Promise<void>;
196
+ declare function broadcastUpdate<TKey extends OnyxKey>(key: TKey, value: OnyxValue<TKey>, hasChanged?: 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,15 @@ 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, isFromUpdate?: boolean): Promise<void>;
257
+ declare function mergeCollectionWithPatches<TKey extends CollectionKeyBase, TMap>(collectionKey: TKey, collection: OnyxMergeCollectionInput<TKey, TMap>, mergeReplaceNullPatches?: MultiMergeReplaceNullPatches): Promise<void>;
258
+ /**
259
+ * Sets keys in a collection by replacing all targeted collection members with new values.
260
+ * Any existing collection members not included in the new data will not be removed.
261
+ *
262
+ * @param collectionKey e.g. `ONYXKEYS.COLLECTION.REPORT`
263
+ * @param collection Object collection keyed by individual collection member keys and values
264
+ */
265
+ declare function partialSetCollection<TKey extends CollectionKeyBase, TMap>(collectionKey: TKey, collection: OnyxMergeCollectionInput<TKey, TMap>): Promise<void>;
258
266
  declare function logKeyChanged(onyxMethod: Extract<OnyxMethod, 'set' | 'merge'>, key: OnyxKey, value: unknown, hasChanged: boolean): void;
259
267
  declare function logKeyRemoved(onyxMethod: Extract<OnyxMethod, 'set' | 'merge'>, key: OnyxKey): void;
260
268
  /**
@@ -318,6 +326,7 @@ declare const OnyxUtils: {
318
326
  reduceCollectionWithSelector: typeof reduceCollectionWithSelector;
319
327
  updateSnapshots: typeof updateSnapshots;
320
328
  mergeCollectionWithPatches: typeof mergeCollectionWithPatches;
329
+ partialSetCollection: typeof partialSetCollection;
321
330
  logKeyChanged: typeof logKeyChanged;
322
331
  logKeyRemoved: typeof logKeyRemoved;
323
332
  };
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, notifyUseOnyxHookSubscribers = true) {
506
+ function keysChanged(collectionKey, partialCollection, partialPreviousCollection, notifyConnectSubscribers = true, notifyWithOnyxSubscribers = 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,8 +531,7 @@ 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
- // Check if it's a useOnyx or a regular Onyx.connect() subscriber
535
- if ((subscriber.isUseOnyxSubscriber && !notifyUseOnyxHookSubscribers) || (!subscriber.isUseOnyxSubscriber && !notifyConnectSubscribers)) {
534
+ if (!notifyConnectSubscribers) {
536
535
  continue;
537
536
  }
538
537
  // If they are subscribed to the collection key and using waitForCollectionCallback then we'll
@@ -662,7 +661,7 @@ function keysChanged(collectionKey, partialCollection, partialPreviousCollection
662
661
  * @example
663
662
  * keyChanged(key, value, subscriber => subscriber.initWithStoredValues === false)
664
663
  */
665
- 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) {
666
665
  var _a, _b;
667
666
  // Add or remove this key from the recentlyAccessedKeys lists
668
667
  if (value !== null) {
@@ -701,8 +700,7 @@ function keyChanged(key, value, previousValue, canUpdateSubscriber = () => true,
701
700
  }
702
701
  // Subscriber is a regular call to connect() and provided a callback
703
702
  if (typeof subscriber.callback === 'function') {
704
- // Check if it's a useOnyx or a regular Onyx.connect() subscriber
705
- if ((subscriber.isUseOnyxSubscriber && !notifyUseOnyxHookSubscribers) || (!subscriber.isUseOnyxSubscriber && !notifyConnectSubscribers)) {
703
+ if (!notifyConnectSubscribers) {
706
704
  continue;
707
705
  }
708
706
  if (lastConnectionCallbackData.has(subscriber.subscriptionID) && lastConnectionCallbackData.get(subscriber.subscriptionID) === value) {
@@ -881,9 +879,9 @@ function getCollectionDataAndSendAsObject(matchingKeys, mapping) {
881
879
  * @example
882
880
  * scheduleSubscriberUpdate(key, value, subscriber => subscriber.initWithStoredValues === false)
883
881
  */
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));
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));
887
885
  return Promise.all([maybeFlushBatchUpdates(), promise]).then(() => undefined);
888
886
  }
889
887
  /**
@@ -891,9 +889,9 @@ function scheduleSubscriberUpdate(key, value, previousValue, canUpdateSubscriber
891
889
  * so that keysChanged() is triggered for the collection and not keyChanged(). If this was not done, then the
892
890
  * subscriber callbacks receive the data in a different format than they normally expect and it breaks code.
893
891
  */
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));
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));
897
895
  return Promise.all([maybeFlushBatchUpdates(), promise]).then(() => undefined);
898
896
  }
899
897
  /**
@@ -943,7 +941,7 @@ function evictStorageAndRetry(error, onyxMethod, ...args) {
943
941
  /**
944
942
  * Notifies subscribers and writes current value to cache
945
943
  */
946
- function broadcastUpdate(key, value, hasChanged, isFromUpdate = false) {
944
+ function broadcastUpdate(key, value, hasChanged) {
947
945
  const prevValue = OnyxCache_1.default.get(key, false);
948
946
  // Update subscribers if the cached value has changed, or when the subscriber specifically requires
949
947
  // all updates regardless of value changes (indicated by initWithStoredValues set to false).
@@ -953,7 +951,7 @@ function broadcastUpdate(key, value, hasChanged, isFromUpdate = false) {
953
951
  else {
954
952
  OnyxCache_1.default.addToAccessedKeys(key);
955
953
  }
956
- return scheduleSubscriberUpdate(key, value, prevValue, (subscriber) => hasChanged || (subscriber === null || subscriber === void 0 ? void 0 : subscriber.initWithStoredValues) === false, isFromUpdate).then(() => undefined);
954
+ return scheduleSubscriberUpdate(key, value, prevValue, (subscriber) => hasChanged || (subscriber === null || subscriber === void 0 ? void 0 : subscriber.initWithStoredValues) === false).then(() => undefined);
957
955
  }
958
956
  function hasPendingMergeForKey(key) {
959
957
  return !!mergeQueue[key];
@@ -1231,7 +1229,7 @@ function updateSnapshots(data, mergeFn) {
1231
1229
  * @param mergeReplaceNullPatches Record where the key is a collection member key and the value is a list of
1232
1230
  * tuples that we'll use to replace the nested objects of that collection member record with something else.
1233
1231
  */
1234
- function mergeCollectionWithPatches(collectionKey, collection, mergeReplaceNullPatches, isFromUpdate = false) {
1232
+ function mergeCollectionWithPatches(collectionKey, collection, mergeReplaceNullPatches) {
1235
1233
  if (!isValidNonEmptyCollectionForMerge(collection)) {
1236
1234
  Logger.logInfo('mergeCollection() called with invalid or empty value. Skipping this update.');
1237
1235
  return Promise.resolve();
@@ -1313,7 +1311,7 @@ function mergeCollectionWithPatches(collectionKey, collection, mergeReplaceNullP
1313
1311
  // and update all subscribers
1314
1312
  const promiseUpdate = previousCollectionPromise.then((previousCollection) => {
1315
1313
  OnyxCache_1.default.merge(finalMergedCollection);
1316
- return scheduleNotifyCollectionSubscribers(collectionKey, finalMergedCollection, previousCollection, isFromUpdate);
1314
+ return scheduleNotifyCollectionSubscribers(collectionKey, finalMergedCollection, previousCollection);
1317
1315
  });
1318
1316
  return Promise.all(promises)
1319
1317
  .catch((error) => evictStorageAndRetry(error, mergeCollectionWithPatches, collectionKey, resultCollection))
@@ -1324,6 +1322,53 @@ function mergeCollectionWithPatches(collectionKey, collection, mergeReplaceNullP
1324
1322
  })
1325
1323
  .then(() => undefined);
1326
1324
  }
1325
+ /**
1326
+ * Sets keys in a collection by replacing all targeted collection members with new values.
1327
+ * Any existing collection members not included in the new data will not be removed.
1328
+ *
1329
+ * @param collectionKey e.g. `ONYXKEYS.COLLECTION.REPORT`
1330
+ * @param collection Object collection keyed by individual collection member keys and values
1331
+ */
1332
+ function partialSetCollection(collectionKey, collection) {
1333
+ let resultCollection = collection;
1334
+ let resultCollectionKeys = Object.keys(resultCollection);
1335
+ // Confirm all the collection keys belong to the same parent
1336
+ if (!doAllCollectionItemsBelongToSameParent(collectionKey, resultCollectionKeys)) {
1337
+ Logger.logAlert(`setCollection called with keys that do not belong to the same parent ${collectionKey}. Skipping this update.`);
1338
+ return Promise.resolve();
1339
+ }
1340
+ if (skippableCollectionMemberIDs.size) {
1341
+ resultCollection = resultCollectionKeys.reduce((result, key) => {
1342
+ try {
1343
+ const [, collectionMemberID] = splitCollectionMemberKey(key, collectionKey);
1344
+ // If the collection member key is a skippable one we set its value to null.
1345
+ // eslint-disable-next-line no-param-reassign
1346
+ result[key] = !skippableCollectionMemberIDs.has(collectionMemberID) ? resultCollection[key] : null;
1347
+ }
1348
+ catch (_a) {
1349
+ // Something went wrong during split, so we assign the data to result anyway.
1350
+ // eslint-disable-next-line no-param-reassign
1351
+ result[key] = resultCollection[key];
1352
+ }
1353
+ return result;
1354
+ }, {});
1355
+ }
1356
+ resultCollectionKeys = Object.keys(resultCollection);
1357
+ return getAllKeys().then((persistedKeys) => {
1358
+ const mutableCollection = Object.assign({}, resultCollection);
1359
+ const existingKeys = resultCollectionKeys.filter((key) => persistedKeys.has(key));
1360
+ const previousCollection = getCachedCollection(collectionKey, existingKeys);
1361
+ const keyValuePairs = prepareKeyValuePairsForStorage(mutableCollection, true);
1362
+ keyValuePairs.forEach(([key, value]) => OnyxCache_1.default.set(key, value));
1363
+ const updatePromise = scheduleNotifyCollectionSubscribers(collectionKey, mutableCollection, previousCollection);
1364
+ return storage_1.default.multiSet(keyValuePairs)
1365
+ .catch((error) => evictStorageAndRetry(error, partialSetCollection, collectionKey, collection))
1366
+ .then(() => {
1367
+ sendActionToDevTools(METHOD.SET_COLLECTION, undefined, mutableCollection);
1368
+ return updatePromise;
1369
+ });
1370
+ });
1371
+ }
1327
1372
  function logKeyChanged(onyxMethod, key, value, hasChanged) {
1328
1373
  Logger.logInfo(`${onyxMethod} called for key: ${key}${underscore_1.default.isObject(value) ? ` properties: ${underscore_1.default.keys(value).join(',')}` : ''} hasChanged: ${hasChanged}`);
1329
1374
  }
@@ -1391,6 +1436,7 @@ const OnyxUtils = {
1391
1436
  reduceCollectionWithSelector,
1392
1437
  updateSnapshots,
1393
1438
  mergeCollectionWithPatches,
1439
+ partialSetCollection,
1394
1440
  logKeyChanged,
1395
1441
  logKeyRemoved,
1396
1442
  };
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.139",
3
+ "version": "2.0.141",
4
4
  "author": "Expensify, Inc.",
5
5
  "homepage": "https://expensify.com",
6
6
  "description": "State management for React Native",