react-native-onyx 3.0.44 → 3.0.46
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 +8 -11
- package/dist/OnyxMerge/index.js +2 -3
- package/dist/OnyxMerge/index.native.js +2 -3
- package/dist/OnyxMerge/types.d.ts +0 -1
- package/dist/OnyxSnapshotCache.d.ts +1 -2
- package/dist/OnyxSnapshotCache.js +2 -4
- package/dist/OnyxUtils.d.ts +2 -17
- package/dist/OnyxUtils.js +39 -74
- package/dist/useOnyx.d.ts +0 -4
- package/dist/useOnyx.js +3 -5
- package/package.json +1 -1
package/dist/Onyx.js
CHANGED
|
@@ -240,9 +240,8 @@ function merge(key, changes) {
|
|
|
240
240
|
OnyxUtils_1.default.logKeyRemoved(OnyxUtils_1.default.METHOD.MERGE, key);
|
|
241
241
|
return Promise.resolve();
|
|
242
242
|
}
|
|
243
|
-
return OnyxMerge_1.default.applyMerge(key, existingValue, validChanges).then(({ mergedValue
|
|
243
|
+
return OnyxMerge_1.default.applyMerge(key, existingValue, validChanges).then(({ mergedValue }) => {
|
|
244
244
|
OnyxUtils_1.default.sendActionToDevTools(OnyxUtils_1.default.METHOD.MERGE, key, changes, mergedValue);
|
|
245
|
-
return updatePromise;
|
|
246
245
|
});
|
|
247
246
|
}
|
|
248
247
|
catch (error) {
|
|
@@ -341,14 +340,6 @@ function clear(keysToPreserve = []) {
|
|
|
341
340
|
// If it isn't preserved and doesn't have a default, we'll remove it
|
|
342
341
|
keysToBeClearedFromStorage.push(key);
|
|
343
342
|
}
|
|
344
|
-
const updatePromises = [];
|
|
345
|
-
// Notify the subscribers for each key/value group so they can receive the new values
|
|
346
|
-
for (const [key, value] of Object.entries(keyValuesToResetIndividually)) {
|
|
347
|
-
updatePromises.push(OnyxUtils_1.default.scheduleSubscriberUpdate(key, value));
|
|
348
|
-
}
|
|
349
|
-
for (const [key, value] of Object.entries(keyValuesToResetAsCollection)) {
|
|
350
|
-
updatePromises.push(OnyxUtils_1.default.scheduleNotifyCollectionSubscribers(key, value.newValues, value.oldValues));
|
|
351
|
-
}
|
|
352
343
|
// Exclude RAM-only keys to prevent them from being saved to storage
|
|
353
344
|
const defaultKeyValuePairs = Object.entries(Object.keys(defaultKeyStates)
|
|
354
345
|
.filter((key) => !keysToPreserve.includes(key) && !OnyxUtils_1.default.isRamOnlyKey(key))
|
|
@@ -365,7 +356,13 @@ function clear(keysToPreserve = []) {
|
|
|
365
356
|
.then(() => storage_1.default.multiSet(defaultKeyValuePairs))
|
|
366
357
|
.then(() => {
|
|
367
358
|
DevTools_1.default.clearState(keysToPreserve);
|
|
368
|
-
|
|
359
|
+
// Notify the subscribers for each key/value group so they can receive the new values
|
|
360
|
+
for (const [key, value] of Object.entries(keyValuesToResetIndividually)) {
|
|
361
|
+
OnyxUtils_1.default.keyChanged(key, value);
|
|
362
|
+
}
|
|
363
|
+
for (const [key, value] of Object.entries(keyValuesToResetAsCollection)) {
|
|
364
|
+
OnyxUtils_1.default.keysChanged(key, value.newValues, value.oldValues);
|
|
365
|
+
}
|
|
369
366
|
});
|
|
370
367
|
})
|
|
371
368
|
.then(() => undefined);
|
package/dist/OnyxMerge/index.js
CHANGED
|
@@ -13,17 +13,16 @@ const applyMerge = (key, existingValue, validChanges) => {
|
|
|
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
|
-
|
|
16
|
+
OnyxUtils_1.default.broadcastUpdate(key, mergedValue, hasChanged);
|
|
17
17
|
const shouldSkipStorageOperations = !hasChanged || OnyxUtils_1.default.isRamOnlyKey(key);
|
|
18
18
|
// If the value has not changed, calling Storage.setItem() would be redundant and a waste of performance, so return early instead.
|
|
19
19
|
// If the key is marked as RAM-only, it should not be saved nor updated in the storage.
|
|
20
20
|
if (shouldSkipStorageOperations) {
|
|
21
|
-
return Promise.resolve({ mergedValue
|
|
21
|
+
return Promise.resolve({ mergedValue });
|
|
22
22
|
}
|
|
23
23
|
// For web platforms we use `setItem` since the object was already merged with its changes before.
|
|
24
24
|
return storage_1.default.setItem(key, mergedValue).then(() => ({
|
|
25
25
|
mergedValue,
|
|
26
|
-
updatePromise,
|
|
27
26
|
}));
|
|
28
27
|
};
|
|
29
28
|
const OnyxMerge = {
|
|
@@ -19,18 +19,17 @@ 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
|
-
|
|
22
|
+
OnyxUtils_1.default.broadcastUpdate(key, mergedValue, hasChanged);
|
|
23
23
|
const shouldSkipStorageOperations = !hasChanged || OnyxUtils_1.default.isRamOnlyKey(key);
|
|
24
24
|
// If the value has not changed, calling Storage.setItem() would be redundant and a waste of performance, so return early instead.
|
|
25
25
|
// If the key is marked as RAM-only, it should not be saved nor updated in the storage.
|
|
26
26
|
if (shouldSkipStorageOperations) {
|
|
27
|
-
return Promise.resolve({ mergedValue
|
|
27
|
+
return Promise.resolve({ mergedValue });
|
|
28
28
|
}
|
|
29
29
|
// For native platforms we use `mergeItem` that will take advantage of JSON_PATCH and JSON_REPLACE SQL operations to
|
|
30
30
|
// merge the object in a performant way.
|
|
31
31
|
return storage_1.default.mergeItem(key, batchedChanges, replaceNullPatches).then(() => ({
|
|
32
32
|
mergedValue,
|
|
33
|
-
updatePromise,
|
|
34
33
|
}));
|
|
35
34
|
};
|
|
36
35
|
const OnyxMerge = {
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import type { OnyxInput, OnyxKey } from '../types';
|
|
2
2
|
type ApplyMergeResult<TValue> = {
|
|
3
3
|
mergedValue: TValue;
|
|
4
|
-
updatePromise: Promise<void>;
|
|
5
4
|
};
|
|
6
5
|
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
6
|
export type { ApplyMerge, ApplyMergeResult };
|
|
@@ -39,12 +39,11 @@ declare class OnyxSnapshotCache {
|
|
|
39
39
|
*
|
|
40
40
|
* - `selector`: Different selectors produce different results, so each selector needs its own cache entry
|
|
41
41
|
* - `initWithStoredValues`: This flag changes the initial loading behavior and affects the returned fetch status
|
|
42
|
-
* - `allowStaleData`: Controls whether stale data can be returned during pending merges, affecting result timing
|
|
43
42
|
*
|
|
44
43
|
* Other options like `canEvict`, `reuseConnection`, and `allowDynamicKey` don't affect the data transformation
|
|
45
44
|
* or timing behavior of getSnapshot, so they're excluded from the cache key for better cache hit rates.
|
|
46
45
|
*/
|
|
47
|
-
registerConsumer<TKey extends OnyxKey, TReturnValue>(options: Pick<UseOnyxOptions<TKey, TReturnValue>, 'selector' | 'initWithStoredValues'
|
|
46
|
+
registerConsumer<TKey extends OnyxKey, TReturnValue>(options: Pick<UseOnyxOptions<TKey, TReturnValue>, 'selector' | 'initWithStoredValues'>): string;
|
|
48
47
|
/**
|
|
49
48
|
* Deregister a consumer for a cache key.
|
|
50
49
|
* Decrements reference counter and removes cache entry if no consumers remain.
|
|
@@ -36,18 +36,16 @@ class OnyxSnapshotCache {
|
|
|
36
36
|
*
|
|
37
37
|
* - `selector`: Different selectors produce different results, so each selector needs its own cache entry
|
|
38
38
|
* - `initWithStoredValues`: This flag changes the initial loading behavior and affects the returned fetch status
|
|
39
|
-
* - `allowStaleData`: Controls whether stale data can be returned during pending merges, affecting result timing
|
|
40
39
|
*
|
|
41
40
|
* Other options like `canEvict`, `reuseConnection`, and `allowDynamicKey` don't affect the data transformation
|
|
42
41
|
* or timing behavior of getSnapshot, so they're excluded from the cache key for better cache hit rates.
|
|
43
42
|
*/
|
|
44
43
|
registerConsumer(options) {
|
|
45
|
-
var _a
|
|
44
|
+
var _a;
|
|
46
45
|
const selectorID = (options === null || options === void 0 ? void 0 : options.selector) ? this.getSelectorID(options.selector) : 'no_selector';
|
|
47
46
|
// Create options hash without expensive JSON.stringify
|
|
48
47
|
const initWithStoredValues = (_a = options === null || options === void 0 ? void 0 : options.initWithStoredValues) !== null && _a !== void 0 ? _a : true;
|
|
49
|
-
const
|
|
50
|
-
const cacheKey = `${selectorID}_${initWithStoredValues}_${allowStaleData}`;
|
|
48
|
+
const cacheKey = `${selectorID}_${initWithStoredValues}`;
|
|
51
49
|
// Increment reference count for this cache key
|
|
52
50
|
const currentCount = this.cacheKeyRefCounts.get(cacheKey) || 0;
|
|
53
51
|
this.cacheKeyRefCounts.set(cacheKey, currentCount + 1);
|
package/dist/OnyxUtils.d.ts
CHANGED
|
@@ -186,7 +186,7 @@ declare function keyChanged<TKey extends OnyxKey>(key: TKey, value: OnyxValue<TK
|
|
|
186
186
|
/**
|
|
187
187
|
* Sends the data obtained from the keys to the connection.
|
|
188
188
|
*/
|
|
189
|
-
declare function sendDataToConnection<TKey extends OnyxKey>(mapping: CallbackToStateMapping<TKey>,
|
|
189
|
+
declare function sendDataToConnection<TKey extends OnyxKey>(mapping: CallbackToStateMapping<TKey>, matchedKey: TKey | undefined): void;
|
|
190
190
|
/**
|
|
191
191
|
* We check to see if this key is flagged as safe for eviction and add it to the recentlyAccessedKeys list so that when we
|
|
192
192
|
* run out of storage the least recently accessed key can be removed.
|
|
@@ -196,19 +196,6 @@ declare function addKeyToRecentlyAccessedIfNeeded<TKey extends OnyxKey>(key: TKe
|
|
|
196
196
|
* Gets the data for a given an array of matching keys, combines them into an object, and sends the result back to the subscriber.
|
|
197
197
|
*/
|
|
198
198
|
declare function getCollectionDataAndSendAsObject<TKey extends OnyxKey>(matchingKeys: CollectionKeyBase[], mapping: CallbackToStateMapping<TKey>): void;
|
|
199
|
-
/**
|
|
200
|
-
* Schedules an update that will be appended to the macro task queue (so it doesn't update the subscribers immediately).
|
|
201
|
-
*
|
|
202
|
-
* @example
|
|
203
|
-
* scheduleSubscriberUpdate(key, value, subscriber => subscriber.initWithStoredValues === false)
|
|
204
|
-
*/
|
|
205
|
-
declare function scheduleSubscriberUpdate<TKey extends OnyxKey>(key: TKey, value: OnyxValue<TKey>, canUpdateSubscriber?: (subscriber?: CallbackToStateMapping<OnyxKey>) => boolean, isProcessingCollectionUpdate?: boolean): Promise<void>;
|
|
206
|
-
/**
|
|
207
|
-
* This method is similar to scheduleSubscriberUpdate but it is built for working specifically with collections
|
|
208
|
-
* so that keysChanged() is triggered for the collection and not keyChanged(). If this was not done, then the
|
|
209
|
-
* subscriber callbacks receive the data in a different format than they normally expect and it breaks code.
|
|
210
|
-
*/
|
|
211
|
-
declare function scheduleNotifyCollectionSubscribers<TKey extends OnyxKey>(key: TKey, value: OnyxCollection<KeyValueMapping[TKey]>, previousValue?: OnyxCollection<KeyValueMapping[TKey]>): Promise<void>;
|
|
212
199
|
/**
|
|
213
200
|
* Remove a key from Onyx and update the subscribers
|
|
214
201
|
*/
|
|
@@ -224,7 +211,7 @@ declare function retryOperation<TMethod extends RetriableOnyxOperation>(error: E
|
|
|
224
211
|
/**
|
|
225
212
|
* Notifies subscribers and writes current value to cache
|
|
226
213
|
*/
|
|
227
|
-
declare function broadcastUpdate<TKey extends OnyxKey>(key: TKey, value: OnyxValue<TKey>, hasChanged?: boolean):
|
|
214
|
+
declare function broadcastUpdate<TKey extends OnyxKey>(key: TKey, value: OnyxValue<TKey>, hasChanged?: boolean): void;
|
|
228
215
|
declare function hasPendingMergeForKey(key: OnyxKey): boolean;
|
|
229
216
|
/**
|
|
230
217
|
* Storage expects array like: [["@MyApp_user", value_1], ["@MyApp_key", value_2]]
|
|
@@ -370,8 +357,6 @@ declare const OnyxUtils: {
|
|
|
370
357
|
sendDataToConnection: typeof sendDataToConnection;
|
|
371
358
|
getCollectionKey: typeof getCollectionKey;
|
|
372
359
|
getCollectionDataAndSendAsObject: typeof getCollectionDataAndSendAsObject;
|
|
373
|
-
scheduleSubscriberUpdate: typeof scheduleSubscriberUpdate;
|
|
374
|
-
scheduleNotifyCollectionSubscribers: typeof scheduleNotifyCollectionSubscribers;
|
|
375
360
|
remove: typeof remove;
|
|
376
361
|
reportStorageQuota: typeof reportStorageQuota;
|
|
377
362
|
retryOperation: typeof retryOperation;
|
package/dist/OnyxUtils.js
CHANGED
|
@@ -74,8 +74,6 @@ const MAX_STORAGE_OPERATION_RETRY_ATTEMPTS = 5;
|
|
|
74
74
|
// Key/value store of Onyx key and arrays of values to merge
|
|
75
75
|
let mergeQueue = {};
|
|
76
76
|
let mergeQueuePromise = {};
|
|
77
|
-
// Used to schedule subscriber update to the macro task queue
|
|
78
|
-
let nextMacrotaskPromise = null;
|
|
79
77
|
// Holds a mapping of all the React components that want their state subscribed to a store key
|
|
80
78
|
let callbackToStateMapping = {};
|
|
81
79
|
// Keeps a copy of the values of the onyx collection keys as a map for faster lookups
|
|
@@ -586,6 +584,7 @@ function keysChanged(collectionKey, partialCollection, partialPreviousCollection
|
|
|
586
584
|
// If they are subscribed to the collection key and using waitForCollectionCallback then we'll
|
|
587
585
|
// send the whole cached collection.
|
|
588
586
|
if (isSubscribedToCollectionKey) {
|
|
587
|
+
lastConnectionCallbackData.set(subscriber.subscriptionID, cachedCollection);
|
|
589
588
|
if (subscriber.waitForCollectionCallback) {
|
|
590
589
|
subscriber.callback(cachedCollection, subscriber.key, partialCollection);
|
|
591
590
|
continue;
|
|
@@ -668,6 +667,7 @@ function keyChanged(key, value, canUpdateSubscriber = () => true, isProcessingCo
|
|
|
668
667
|
cachedCollections[subscriber.key] = cachedCollection;
|
|
669
668
|
}
|
|
670
669
|
cachedCollection[key] = value;
|
|
670
|
+
lastConnectionCallbackData.set(subscriber.subscriptionID, cachedCollection);
|
|
671
671
|
subscriber.callback(cachedCollection, subscriber.key, { [key]: value });
|
|
672
672
|
continue;
|
|
673
673
|
}
|
|
@@ -682,22 +682,32 @@ function keyChanged(key, value, canUpdateSubscriber = () => true, isProcessingCo
|
|
|
682
682
|
/**
|
|
683
683
|
* Sends the data obtained from the keys to the connection.
|
|
684
684
|
*/
|
|
685
|
-
function sendDataToConnection(mapping,
|
|
685
|
+
function sendDataToConnection(mapping, matchedKey) {
|
|
686
686
|
var _a, _b;
|
|
687
687
|
// If the mapping no longer exists then we should not send any data.
|
|
688
688
|
// This means our subscriber was disconnected.
|
|
689
689
|
if (!callbackToStateMapping[mapping.subscriptionID]) {
|
|
690
690
|
return;
|
|
691
691
|
}
|
|
692
|
+
// Always read the latest value from cache to avoid stale or duplicate data.
|
|
693
|
+
// For collection subscribers with waitForCollectionCallback, read the full collection.
|
|
694
|
+
// For individual key subscribers, read just that key's value.
|
|
695
|
+
let value;
|
|
696
|
+
if (isCollectionKey(mapping.key) && mapping.waitForCollectionCallback) {
|
|
697
|
+
const collection = getCachedCollection(mapping.key);
|
|
698
|
+
value = Object.keys(collection).length > 0 ? collection : undefined;
|
|
699
|
+
}
|
|
700
|
+
else {
|
|
701
|
+
value = OnyxCache_1.default.get(matchedKey !== null && matchedKey !== void 0 ? matchedKey : mapping.key);
|
|
702
|
+
}
|
|
692
703
|
// For regular callbacks, we never want to pass null values, but always just undefined if a value is not set in cache or storage.
|
|
693
|
-
|
|
704
|
+
value = value === null ? undefined : value;
|
|
694
705
|
const lastValue = lastConnectionCallbackData.get(mapping.subscriptionID);
|
|
695
|
-
lastConnectionCallbackData.get(mapping.subscriptionID);
|
|
696
706
|
// If the value has not changed we do not need to trigger the callback
|
|
697
|
-
if (lastConnectionCallbackData.has(mapping.subscriptionID) &&
|
|
707
|
+
if (lastConnectionCallbackData.has(mapping.subscriptionID) && (0, fast_equals_1.shallowEqual)(lastValue, value)) {
|
|
698
708
|
return;
|
|
699
709
|
}
|
|
700
|
-
(_b = (_a = mapping).callback) === null || _b === void 0 ? void 0 : _b.call(_a,
|
|
710
|
+
(_b = (_a = mapping).callback) === null || _b === void 0 ? void 0 : _b.call(_a, value, matchedKey);
|
|
701
711
|
}
|
|
702
712
|
/**
|
|
703
713
|
* We check to see if this key is flagged as safe for eviction and add it to the recentlyAccessedKeys list so that when we
|
|
@@ -716,50 +726,16 @@ function addKeyToRecentlyAccessedIfNeeded(key) {
|
|
|
716
726
|
* Gets the data for a given an array of matching keys, combines them into an object, and sends the result back to the subscriber.
|
|
717
727
|
*/
|
|
718
728
|
function getCollectionDataAndSendAsObject(matchingKeys, mapping) {
|
|
719
|
-
multiGet(matchingKeys).then((
|
|
720
|
-
|
|
721
|
-
sendDataToConnection(mapping, data, mapping.key);
|
|
729
|
+
multiGet(matchingKeys).then(() => {
|
|
730
|
+
sendDataToConnection(mapping, mapping.key);
|
|
722
731
|
});
|
|
723
732
|
}
|
|
724
|
-
/**
|
|
725
|
-
* Delays promise resolution until the next macrotask to prevent race condition if the key subscription is in progress.
|
|
726
|
-
*
|
|
727
|
-
* @param callback The keyChanged/keysChanged callback
|
|
728
|
-
* */
|
|
729
|
-
function prepareSubscriberUpdate(callback) {
|
|
730
|
-
if (!nextMacrotaskPromise) {
|
|
731
|
-
nextMacrotaskPromise = new Promise((resolve) => {
|
|
732
|
-
setTimeout(() => {
|
|
733
|
-
nextMacrotaskPromise = null;
|
|
734
|
-
resolve();
|
|
735
|
-
}, 0);
|
|
736
|
-
});
|
|
737
|
-
}
|
|
738
|
-
return Promise.all([nextMacrotaskPromise, Promise.resolve().then(callback)]).then();
|
|
739
|
-
}
|
|
740
|
-
/**
|
|
741
|
-
* Schedules an update that will be appended to the macro task queue (so it doesn't update the subscribers immediately).
|
|
742
|
-
*
|
|
743
|
-
* @example
|
|
744
|
-
* scheduleSubscriberUpdate(key, value, subscriber => subscriber.initWithStoredValues === false)
|
|
745
|
-
*/
|
|
746
|
-
function scheduleSubscriberUpdate(key, value, canUpdateSubscriber = () => true, isProcessingCollectionUpdate = false) {
|
|
747
|
-
return prepareSubscriberUpdate(() => keyChanged(key, value, canUpdateSubscriber, isProcessingCollectionUpdate));
|
|
748
|
-
}
|
|
749
|
-
/**
|
|
750
|
-
* This method is similar to scheduleSubscriberUpdate but it is built for working specifically with collections
|
|
751
|
-
* so that keysChanged() is triggered for the collection and not keyChanged(). If this was not done, then the
|
|
752
|
-
* subscriber callbacks receive the data in a different format than they normally expect and it breaks code.
|
|
753
|
-
*/
|
|
754
|
-
function scheduleNotifyCollectionSubscribers(key, value, previousValue) {
|
|
755
|
-
return prepareSubscriberUpdate(() => keysChanged(key, value, previousValue));
|
|
756
|
-
}
|
|
757
733
|
/**
|
|
758
734
|
* Remove a key from Onyx and update the subscribers
|
|
759
735
|
*/
|
|
760
736
|
function remove(key, isProcessingCollectionUpdate) {
|
|
761
737
|
OnyxCache_1.default.drop(key);
|
|
762
|
-
|
|
738
|
+
keyChanged(key, undefined, undefined, isProcessingCollectionUpdate);
|
|
763
739
|
if (isRamOnlyKey(key)) {
|
|
764
740
|
return Promise.resolve();
|
|
765
741
|
}
|
|
@@ -827,7 +803,7 @@ function broadcastUpdate(key, value, hasChanged) {
|
|
|
827
803
|
else {
|
|
828
804
|
OnyxCache_1.default.addToAccessedKeys(key);
|
|
829
805
|
}
|
|
830
|
-
|
|
806
|
+
keyChanged(key, value, (subscriber) => hasChanged || (subscriber === null || subscriber === void 0 ? void 0 : subscriber.initWithStoredValues) === false);
|
|
831
807
|
}
|
|
832
808
|
function hasPendingMergeForKey(key) {
|
|
833
809
|
return !!mergeQueue[key];
|
|
@@ -1002,7 +978,7 @@ function subscribeToKey(connectOptions) {
|
|
|
1002
978
|
const matchedKey = isCollectionKey(mapping.key) && mapping.waitForCollectionCallback ? mapping.key : undefined;
|
|
1003
979
|
// Here we cannot use batching because the nullish value is expected to be set immediately for default props
|
|
1004
980
|
// or they will be undefined.
|
|
1005
|
-
sendDataToConnection(mapping,
|
|
981
|
+
sendDataToConnection(mapping, matchedKey);
|
|
1006
982
|
return;
|
|
1007
983
|
}
|
|
1008
984
|
// When using a callback subscriber we will either trigger the provided callback for each key we find or combine all values
|
|
@@ -1015,15 +991,15 @@ function subscribeToKey(connectOptions) {
|
|
|
1015
991
|
return;
|
|
1016
992
|
}
|
|
1017
993
|
// We did not opt into using waitForCollectionCallback mode so the callback is called for every matching key.
|
|
1018
|
-
multiGet(matchingKeys).then((
|
|
1019
|
-
for (const
|
|
1020
|
-
sendDataToConnection(mapping,
|
|
994
|
+
multiGet(matchingKeys).then(() => {
|
|
995
|
+
for (const key of matchingKeys) {
|
|
996
|
+
sendDataToConnection(mapping, key);
|
|
1021
997
|
}
|
|
1022
998
|
});
|
|
1023
999
|
return;
|
|
1024
1000
|
}
|
|
1025
1001
|
// If we are not subscribed to a collection key then there's only a single key to send an update for.
|
|
1026
|
-
get(mapping.key).then((
|
|
1002
|
+
get(mapping.key).then(() => sendDataToConnection(mapping, mapping.key));
|
|
1027
1003
|
return;
|
|
1028
1004
|
}
|
|
1029
1005
|
console.error('Warning: Onyx.connect() was found without a callback');
|
|
@@ -1151,21 +1127,20 @@ function setWithRetry({ key, value, options }, retryAttempt) {
|
|
|
1151
1127
|
const hasChanged = (options === null || options === void 0 ? void 0 : options.skipCacheCheck) ? true : OnyxCache_1.default.hasValueChanged(key, valueWithoutNestedNullValues);
|
|
1152
1128
|
OnyxUtils.logKeyChanged(OnyxUtils.METHOD.SET, key, value, hasChanged);
|
|
1153
1129
|
// This approach prioritizes fast UI changes without waiting for data to be stored in device storage.
|
|
1154
|
-
|
|
1130
|
+
OnyxUtils.broadcastUpdate(key, valueWithoutNestedNullValues, hasChanged);
|
|
1155
1131
|
// If the value has not changed and this isn't a retry attempt, calling Storage.setItem() would be redundant and a waste of performance, so return early instead.
|
|
1156
1132
|
if (!hasChanged && !retryAttempt) {
|
|
1157
|
-
return
|
|
1133
|
+
return Promise.resolve();
|
|
1158
1134
|
}
|
|
1159
1135
|
// If a key is a RAM-only key or a member of RAM-only collection, we skip the step that modifies the storage
|
|
1160
1136
|
if (isRamOnlyKey(key)) {
|
|
1161
1137
|
OnyxUtils.sendActionToDevTools(OnyxUtils.METHOD.SET, key, valueWithoutNestedNullValues);
|
|
1162
|
-
return
|
|
1138
|
+
return Promise.resolve();
|
|
1163
1139
|
}
|
|
1164
1140
|
return storage_1.default.setItem(key, valueWithoutNestedNullValues)
|
|
1165
1141
|
.catch((error) => OnyxUtils.retryOperation(error, setWithRetry, { key, value: valueWithoutNestedNullValues, options }, retryAttempt))
|
|
1166
1142
|
.then(() => {
|
|
1167
1143
|
OnyxUtils.sendActionToDevTools(OnyxUtils.METHOD.SET, key, valueWithoutNestedNullValues);
|
|
1168
|
-
return updatePromise;
|
|
1169
1144
|
});
|
|
1170
1145
|
}
|
|
1171
1146
|
/**
|
|
@@ -1195,16 +1170,16 @@ function multiSetWithRetry(data, retryAttempt) {
|
|
|
1195
1170
|
}, {});
|
|
1196
1171
|
}
|
|
1197
1172
|
const keyValuePairsToSet = OnyxUtils.prepareKeyValuePairsForStorage(newData, true);
|
|
1198
|
-
const
|
|
1173
|
+
for (const [key, value] of keyValuePairsToSet) {
|
|
1199
1174
|
// When we use multiSet to set a key we want to clear the current delta changes from Onyx.merge that were queued
|
|
1200
1175
|
// before the value was set. If Onyx.merge is currently reading the old value from storage, it will then not apply the changes.
|
|
1201
1176
|
if (OnyxUtils.hasPendingMergeForKey(key)) {
|
|
1202
1177
|
delete OnyxUtils.getMergeQueue()[key];
|
|
1203
1178
|
}
|
|
1204
|
-
// Update cache and optimistically inform subscribers
|
|
1179
|
+
// Update cache and optimistically inform subscribers
|
|
1205
1180
|
OnyxCache_1.default.set(key, value);
|
|
1206
|
-
|
|
1207
|
-
}
|
|
1181
|
+
keyChanged(key, value);
|
|
1182
|
+
}
|
|
1208
1183
|
const keyValuePairsToStore = keyValuePairsToSet.filter((keyValuePair) => {
|
|
1209
1184
|
const [key] = keyValuePair;
|
|
1210
1185
|
// Filter out the RAM-only key value pairs, as they should not be saved to storage
|
|
@@ -1214,9 +1189,7 @@ function multiSetWithRetry(data, retryAttempt) {
|
|
|
1214
1189
|
.catch((error) => OnyxUtils.retryOperation(error, multiSetWithRetry, newData, retryAttempt))
|
|
1215
1190
|
.then(() => {
|
|
1216
1191
|
OnyxUtils.sendActionToDevTools(OnyxUtils.METHOD.MULTI_SET, undefined, newData);
|
|
1217
|
-
|
|
1218
|
-
})
|
|
1219
|
-
.then(() => undefined);
|
|
1192
|
+
});
|
|
1220
1193
|
}
|
|
1221
1194
|
/**
|
|
1222
1195
|
* Sets a collection by replacing all existing collection members with new values.
|
|
@@ -1269,17 +1242,16 @@ function setCollectionWithRetry({ collectionKey, collection }, retryAttempt) {
|
|
|
1269
1242
|
const previousCollection = OnyxUtils.getCachedCollection(collectionKey);
|
|
1270
1243
|
for (const [key, value] of keyValuePairs)
|
|
1271
1244
|
OnyxCache_1.default.set(key, value);
|
|
1272
|
-
|
|
1245
|
+
keysChanged(collectionKey, mutableCollection, previousCollection);
|
|
1273
1246
|
// RAM-only keys are not supposed to be saved to storage
|
|
1274
1247
|
if (isRamOnlyKey(collectionKey)) {
|
|
1275
1248
|
OnyxUtils.sendActionToDevTools(OnyxUtils.METHOD.SET_COLLECTION, undefined, mutableCollection);
|
|
1276
|
-
return
|
|
1249
|
+
return;
|
|
1277
1250
|
}
|
|
1278
1251
|
return storage_1.default.multiSet(keyValuePairs)
|
|
1279
1252
|
.catch((error) => OnyxUtils.retryOperation(error, setCollectionWithRetry, { collectionKey, collection }, retryAttempt))
|
|
1280
1253
|
.then(() => {
|
|
1281
1254
|
OnyxUtils.sendActionToDevTools(OnyxUtils.METHOD.SET_COLLECTION, undefined, mutableCollection);
|
|
1282
|
-
return updatePromise;
|
|
1283
1255
|
});
|
|
1284
1256
|
});
|
|
1285
1257
|
}
|
|
@@ -1380,7 +1352,7 @@ function mergeCollectionWithPatches({ collectionKey, collection, mergeReplaceNul
|
|
|
1380
1352
|
// and update all subscribers
|
|
1381
1353
|
const promiseUpdate = previousCollectionPromise.then((previousCollection) => {
|
|
1382
1354
|
OnyxCache_1.default.merge(finalMergedCollection);
|
|
1383
|
-
|
|
1355
|
+
keysChanged(collectionKey, finalMergedCollection, previousCollection);
|
|
1384
1356
|
});
|
|
1385
1357
|
return Promise.all(promises)
|
|
1386
1358
|
.catch((error) => retryOperation(error, mergeCollectionWithPatches, { collectionKey, collection: resultCollection, mergeReplaceNullPatches, isProcessingCollectionUpdate }, retryAttempt))
|
|
@@ -1433,16 +1405,15 @@ function partialSetCollection({ collectionKey, collection }, retryAttempt) {
|
|
|
1433
1405
|
const keyValuePairs = prepareKeyValuePairsForStorage(mutableCollection, true, undefined, true);
|
|
1434
1406
|
for (const [key, value] of keyValuePairs)
|
|
1435
1407
|
OnyxCache_1.default.set(key, value);
|
|
1436
|
-
|
|
1408
|
+
keysChanged(collectionKey, mutableCollection, previousCollection);
|
|
1437
1409
|
if (isRamOnlyKey(collectionKey)) {
|
|
1438
1410
|
sendActionToDevTools(METHOD.SET_COLLECTION, undefined, mutableCollection);
|
|
1439
|
-
return
|
|
1411
|
+
return;
|
|
1440
1412
|
}
|
|
1441
1413
|
return storage_1.default.multiSet(keyValuePairs)
|
|
1442
1414
|
.catch((error) => retryOperation(error, partialSetCollection, { collectionKey, collection }, retryAttempt))
|
|
1443
1415
|
.then(() => {
|
|
1444
1416
|
sendActionToDevTools(METHOD.SET_COLLECTION, undefined, mutableCollection);
|
|
1445
|
-
return updatePromise;
|
|
1446
1417
|
});
|
|
1447
1418
|
});
|
|
1448
1419
|
}
|
|
@@ -1486,8 +1457,6 @@ const OnyxUtils = {
|
|
|
1486
1457
|
sendDataToConnection,
|
|
1487
1458
|
getCollectionKey,
|
|
1488
1459
|
getCollectionDataAndSendAsObject,
|
|
1489
|
-
scheduleSubscriberUpdate,
|
|
1490
|
-
scheduleNotifyCollectionSubscribers,
|
|
1491
1460
|
remove,
|
|
1492
1461
|
reportStorageQuota,
|
|
1493
1462
|
retryOperation,
|
|
@@ -1542,10 +1511,6 @@ GlobalSettings.addGlobalSettingsChangeListener(({ enablePerformanceMetrics }) =>
|
|
|
1542
1511
|
// @ts-expect-error Reassign
|
|
1543
1512
|
sendDataToConnection = (0, metrics_1.default)(sendDataToConnection, 'OnyxUtils.sendDataToConnection');
|
|
1544
1513
|
// @ts-expect-error Reassign
|
|
1545
|
-
scheduleSubscriberUpdate = (0, metrics_1.default)(scheduleSubscriberUpdate, 'OnyxUtils.scheduleSubscriberUpdate');
|
|
1546
|
-
// @ts-expect-error Reassign
|
|
1547
|
-
scheduleNotifyCollectionSubscribers = (0, metrics_1.default)(scheduleNotifyCollectionSubscribers, 'OnyxUtils.scheduleNotifyCollectionSubscribers');
|
|
1548
|
-
// @ts-expect-error Reassign
|
|
1549
1514
|
remove = (0, metrics_1.default)(remove, 'OnyxUtils.remove');
|
|
1550
1515
|
// @ts-expect-error Reassign
|
|
1551
1516
|
reportStorageQuota = (0, metrics_1.default)(reportStorageQuota, 'OnyxUtils.reportStorageQuota');
|
package/dist/useOnyx.d.ts
CHANGED
|
@@ -11,10 +11,6 @@ type UseOnyxOptions<TKey extends OnyxKey, TReturnValue> = {
|
|
|
11
11
|
* @deprecated This param is going to be removed soon. Use RAM-only keys instead.
|
|
12
12
|
*/
|
|
13
13
|
initWithStoredValues?: boolean;
|
|
14
|
-
/**
|
|
15
|
-
* If set to `true`, data will be retrieved from cache during the first render even if there is a pending merge for the key.
|
|
16
|
-
*/
|
|
17
|
-
allowStaleData?: boolean;
|
|
18
14
|
/**
|
|
19
15
|
* If set to `false`, the connection won't be reused between other subscribers that are listening to the same Onyx key
|
|
20
16
|
* with the same connect configurations.
|
package/dist/useOnyx.js
CHANGED
|
@@ -109,8 +109,7 @@ function useOnyx(key, options, dependencies = []) {
|
|
|
109
109
|
const cacheKey = (0, react_1.useMemo)(() => OnyxSnapshotCache_1.default.registerConsumer({
|
|
110
110
|
selector: options === null || options === void 0 ? void 0 : options.selector,
|
|
111
111
|
initWithStoredValues: options === null || options === void 0 ? void 0 : options.initWithStoredValues,
|
|
112
|
-
|
|
113
|
-
}), [options === null || options === void 0 ? void 0 : options.selector, options === null || options === void 0 ? void 0 : options.initWithStoredValues, options === null || options === void 0 ? void 0 : options.allowStaleData]);
|
|
112
|
+
}), [options === null || options === void 0 ? void 0 : options.selector, options === null || options === void 0 ? void 0 : options.initWithStoredValues]);
|
|
114
113
|
(0, react_1.useEffect)(() => () => OnyxSnapshotCache_1.default.deregisterConsumer(key, cacheKey), [key, cacheKey]);
|
|
115
114
|
(0, react_1.useEffect)(() => {
|
|
116
115
|
// These conditions will ensure we can only handle dynamic collection member keys from the same collection.
|
|
@@ -206,8 +205,7 @@ function useOnyx(key, options, dependencies = []) {
|
|
|
206
205
|
let newFetchStatus;
|
|
207
206
|
// If we have pending merge operations for the key during the first connection, we set the new value to `undefined`
|
|
208
207
|
// and fetch status to `loading` to simulate that it is still being loaded until we have the most updated data.
|
|
209
|
-
|
|
210
|
-
if (isFirstConnectionRef.current && OnyxUtils_1.default.hasPendingMergeForKey(key) && !(options === null || options === void 0 ? void 0 : options.allowStaleData)) {
|
|
208
|
+
if (isFirstConnectionRef.current && OnyxUtils_1.default.hasPendingMergeForKey(key)) {
|
|
211
209
|
newValueRef.current = undefined;
|
|
212
210
|
newFetchStatus = 'loading';
|
|
213
211
|
}
|
|
@@ -248,7 +246,7 @@ function useOnyx(key, options, dependencies = []) {
|
|
|
248
246
|
OnyxSnapshotCache_1.default.setCachedResult(key, cacheKey, resultRef.current);
|
|
249
247
|
}
|
|
250
248
|
return resultRef.current;
|
|
251
|
-
}, [options === null || options === void 0 ? void 0 : options.initWithStoredValues,
|
|
249
|
+
}, [options === null || options === void 0 ? void 0 : options.initWithStoredValues, key, memoizedSelector, cacheKey, previousKey]);
|
|
252
250
|
const subscribe = (0, react_1.useCallback)((onStoreChange) => {
|
|
253
251
|
isConnectingRef.current = true;
|
|
254
252
|
onStoreChangeFnRef.current = onStoreChange;
|