react-native-onyx 3.0.71 → 3.0.73

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
@@ -177,7 +177,7 @@ applied in the order they were called. Note: `Onyx.set()` calls do not work this
177
177
  **Example**
178
178
  ```js
179
179
  Onyx.merge(ONYXKEYS.EMPLOYEE_LIST, ['Joe']); // -> ['Joe']
180
- Onyx.merge(ONYXKEYS.EMPLOYEE_LIST, ['Jack']); // -> ['Joe', 'Jack']
180
+ Onyx.merge(ONYXKEYS.EMPLOYEE_LIST, ['Jack']); // -> ['Jack']
181
181
  Onyx.merge(ONYXKEYS.POLICY, {id: 1}); // -> {id: 1}
182
182
  Onyx.merge(ONYXKEYS.POLICY, {name: 'My Workspace'}); // -> {id: 1, name: 'My Workspace'}
183
183
  ```
package/dist/Onyx.d.ts CHANGED
@@ -92,7 +92,7 @@ declare function multiSet(data: OnyxMultiSetInput): Promise<void>;
92
92
  *
93
93
  * @example
94
94
  * Onyx.merge(ONYXKEYS.EMPLOYEE_LIST, ['Joe']); // -> ['Joe']
95
- * Onyx.merge(ONYXKEYS.EMPLOYEE_LIST, ['Jack']); // -> ['Joe', 'Jack']
95
+ * Onyx.merge(ONYXKEYS.EMPLOYEE_LIST, ['Jack']); // -> ['Jack']
96
96
  * Onyx.merge(ONYXKEYS.POLICY, {id: 1}); // -> {id: 1}
97
97
  * Onyx.merge(ONYXKEYS.POLICY, {name: 'My Workspace'}); // -> {id: 1, name: 'My Workspace'}
98
98
  */
package/dist/Onyx.js CHANGED
@@ -177,7 +177,7 @@ function multiSet(data) {
177
177
  *
178
178
  * @example
179
179
  * Onyx.merge(ONYXKEYS.EMPLOYEE_LIST, ['Joe']); // -> ['Joe']
180
- * Onyx.merge(ONYXKEYS.EMPLOYEE_LIST, ['Jack']); // -> ['Joe', 'Jack']
180
+ * Onyx.merge(ONYXKEYS.EMPLOYEE_LIST, ['Jack']); // -> ['Jack']
181
181
  * Onyx.merge(ONYXKEYS.POLICY, {id: 1}); // -> {id: 1}
182
182
  * Onyx.merge(ONYXKEYS.POLICY, {name: 'My Workspace'}); // -> {id: 1, name: 'My Workspace'}
183
183
  */
package/dist/OnyxUtils.js CHANGED
@@ -454,6 +454,16 @@ function keysChanged(collectionKey, partialCollection, partialPreviousCollection
454
454
  const cachedCollection = getCachedCollection(collectionKey);
455
455
  const previousCollection = partialPreviousCollection !== null && partialPreviousCollection !== void 0 ? partialPreviousCollection : {};
456
456
  const changedMemberKeys = Object.keys(partialCollection !== null && partialCollection !== void 0 ? partialCollection : {});
457
+ // Add or remove the keys from the recentlyAccessedKeys list
458
+ for (const memberKey of changedMemberKeys) {
459
+ const value = partialCollection === null || partialCollection === void 0 ? void 0 : partialCollection[memberKey];
460
+ if (value !== null && value !== undefined) {
461
+ OnyxCache_1.default.addLastAccessedKey(memberKey, false);
462
+ }
463
+ else {
464
+ OnyxCache_1.default.removeLastAccessedKey(memberKey);
465
+ }
466
+ }
457
467
  // Use indexed lookup instead of scanning all subscribers.
458
468
  // We need subscribers for: (1) the collection key itself, and (2) individual changed member keys.
459
469
  const collectionSubscriberIDs = (_a = onyxKeyToSubscriptionIDs.get(collectionKey)) !== null && _a !== void 0 ? _a : [];
@@ -478,12 +488,20 @@ function keysChanged(collectionKey, partialCollection, partialPreviousCollection
478
488
  subscriber.callback(cachedCollection, subscriber.key, partialCollection);
479
489
  continue;
480
490
  }
481
- // Not using waitForCollectionCallback — notify per changed key
491
+ // Not using waitForCollectionCallback — notify per changed key.
492
+ // Re-check the subscription on each iteration because the callback may
493
+ // synchronously disconnect itself (removing it from callbackToStateMapping),
494
+ // in which case we must stop firing further callbacks for this subscriber.
482
495
  for (const dataKey of changedMemberKeys) {
496
+ const currentSubscriber = callbackToStateMapping[subID];
497
+ if (!currentSubscriber || typeof currentSubscriber.callback !== 'function') {
498
+ break;
499
+ }
483
500
  if (cachedCollection[dataKey] === previousCollection[dataKey]) {
484
501
  continue;
485
502
  }
486
- subscriber.callback(cachedCollection[dataKey], dataKey);
503
+ const currentSubscriberCallback = currentSubscriber.callback;
504
+ currentSubscriberCallback(cachedCollection[dataKey], dataKey);
487
505
  }
488
506
  }
489
507
  catch (error) {
@@ -1135,15 +1153,43 @@ function multiSetWithRetry(data, retryAttempt) {
1135
1153
  }, {});
1136
1154
  }
1137
1155
  const keyValuePairsToSet = OnyxUtils.prepareKeyValuePairsForStorage(newData, true);
1156
+ // Group collection members by their parent collection key so each collection can be notified
1157
+ // via a single batched keysChanged() call instead of one keyChanged() per member. For each
1158
+ // collection, `partial` holds the new values being set and `previous` holds the cached values
1159
+ // from before the set, which keysChanged() uses to skip subscribers whose value didn't change.
1160
+ const collectionBatches = new Map();
1138
1161
  for (const [key, value] of keyValuePairsToSet) {
1139
1162
  // When we use multiSet to set a key we want to clear the current delta changes from Onyx.merge that were queued
1140
1163
  // before the value was set. If Onyx.merge is currently reading the old value from storage, it will then not apply the changes.
1141
1164
  if (OnyxUtils.hasPendingMergeForKey(key)) {
1142
1165
  delete OnyxUtils.getMergeQueue()[key];
1143
1166
  }
1144
- // Update cache and optimistically inform subscribers
1145
- OnyxCache_1.default.set(key, value);
1146
- keyChanged(key, value);
1167
+ const collectionKey = OnyxKeys_1.default.getCollectionKey(key);
1168
+ if (collectionKey && OnyxKeys_1.default.isCollectionMemberKey(collectionKey, key)) {
1169
+ // Capture the previous cached value BEFORE calling cache.set() so keysChanged()
1170
+ // can diff old vs new per-member.
1171
+ const previousValue = OnyxCache_1.default.get(key);
1172
+ OnyxCache_1.default.set(key, value);
1173
+ let batch = collectionBatches.get(collectionKey);
1174
+ if (!batch) {
1175
+ batch = { partial: {}, previous: {} };
1176
+ collectionBatches.set(collectionKey, batch);
1177
+ }
1178
+ batch.partial[key] = value;
1179
+ batch.previous[key] = previousValue;
1180
+ }
1181
+ else {
1182
+ // Non-collection keys are notified inline (cache.set + keyChanged in iteration order)
1183
+ // so re-entrant callbacks (e.g. Onyx.set inside a callback) see consistent cache
1184
+ // and subscriber state, matching the original per-key notification semantics.
1185
+ OnyxCache_1.default.set(key, value);
1186
+ keyChanged(key, value);
1187
+ }
1188
+ }
1189
+ // One keysChanged() per collection — fires each collection-level subscriber once and lets
1190
+ // keysChanged() internally decide which individual member subscribers need notification.
1191
+ for (const [collectionKey, batch] of collectionBatches) {
1192
+ keysChanged(collectionKey, batch.partial, batch.previous);
1147
1193
  }
1148
1194
  const keyValuePairsToStore = keyValuePairsToSet.filter((keyValuePair) => {
1149
1195
  const [key] = keyValuePair;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-onyx",
3
- "version": "3.0.71",
3
+ "version": "3.0.73",
4
4
  "author": "Expensify, Inc.",
5
5
  "homepage": "https://expensify.com",
6
6
  "description": "State management for React Native",