react-native-onyx 2.0.89 → 2.0.91
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.d.ts +2 -2
- package/dist/Onyx.js +103 -18
- package/dist/OnyxUtils.d.ts +12 -1
- package/dist/OnyxUtils.js +50 -2
- package/dist/types.d.ts +5 -0
- package/dist/useOnyx.d.ts +6 -1
- package/dist/useOnyx.js +2 -2
- package/package.json +1 -1
package/dist/Onyx.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ import * as Logger from './Logger';
|
|
|
2
2
|
import type { CollectionKeyBase, ConnectOptions, InitOptions, Mapping, OnyxKey, OnyxMergeCollectionInput, OnyxMergeInput, OnyxMultiSetInput, OnyxSetInput, OnyxUpdate } from './types';
|
|
3
3
|
import type { Connection } from './OnyxConnectionManager';
|
|
4
4
|
/** Initialize the store with actions and listening for storage events */
|
|
5
|
-
declare function init({ keys, initialKeyStates, safeEvictionKeys, maxCachedKeysCount, shouldSyncMultipleInstances, debugSetState, enablePerformanceMetrics, }: InitOptions): void;
|
|
5
|
+
declare function init({ keys, initialKeyStates, safeEvictionKeys, maxCachedKeysCount, shouldSyncMultipleInstances, debugSetState, enablePerformanceMetrics, skippableCollectionMemberIDs, }: InitOptions): void;
|
|
6
6
|
/**
|
|
7
7
|
* Connects to an Onyx key given the options passed and listens to its changes.
|
|
8
8
|
*
|
|
@@ -132,7 +132,7 @@ declare function update(data: OnyxUpdate[]): Promise<void>;
|
|
|
132
132
|
* @param collectionKey e.g. `ONYXKEYS.COLLECTION.REPORT`
|
|
133
133
|
* @param collection Object collection keyed by individual collection member keys and values
|
|
134
134
|
*/
|
|
135
|
-
declare function setCollection<TKey extends CollectionKeyBase, TMap
|
|
135
|
+
declare function setCollection<TKey extends CollectionKeyBase, TMap>(collectionKey: TKey, collection: OnyxMergeCollectionInput<TKey, TMap>): Promise<void>;
|
|
136
136
|
declare const Onyx: {
|
|
137
137
|
METHOD: {
|
|
138
138
|
readonly SET: "set";
|
package/dist/Onyx.js
CHANGED
|
@@ -41,13 +41,14 @@ const OnyxConnectionManager_1 = __importDefault(require("./OnyxConnectionManager
|
|
|
41
41
|
const GlobalSettings = __importStar(require("./GlobalSettings"));
|
|
42
42
|
const metrics_1 = __importDefault(require("./metrics"));
|
|
43
43
|
/** Initialize the store with actions and listening for storage events */
|
|
44
|
-
function init({ keys = {}, initialKeyStates = {}, safeEvictionKeys = [], maxCachedKeysCount = 1000, shouldSyncMultipleInstances = Boolean(global.localStorage), debugSetState = false, enablePerformanceMetrics = false, }) {
|
|
44
|
+
function init({ keys = {}, initialKeyStates = {}, safeEvictionKeys = [], maxCachedKeysCount = 1000, shouldSyncMultipleInstances = Boolean(global.localStorage), debugSetState = false, enablePerformanceMetrics = false, skippableCollectionMemberIDs = [], }) {
|
|
45
45
|
var _a;
|
|
46
46
|
if (enablePerformanceMetrics) {
|
|
47
47
|
GlobalSettings.setPerformanceMetricsEnabled(true);
|
|
48
48
|
applyDecorators();
|
|
49
49
|
}
|
|
50
50
|
storage_1.default.init();
|
|
51
|
+
OnyxUtils_1.default.setSkippableCollectionMemberIDs(new Set(skippableCollectionMemberIDs));
|
|
51
52
|
if (shouldSyncMultipleInstances) {
|
|
52
53
|
(_a = storage_1.default.keepInstancesSync) === null || _a === void 0 ? void 0 : _a.call(storage_1.default, (key, value) => {
|
|
53
54
|
const prevValue = OnyxCache_1.default.get(key, false);
|
|
@@ -122,6 +123,20 @@ function set(key, value) {
|
|
|
122
123
|
if (OnyxUtils_1.default.hasPendingMergeForKey(key)) {
|
|
123
124
|
delete OnyxUtils_1.default.getMergeQueue()[key];
|
|
124
125
|
}
|
|
126
|
+
const skippableCollectionMemberIDs = OnyxUtils_1.default.getSkippableCollectionMemberIDs();
|
|
127
|
+
if (skippableCollectionMemberIDs.size) {
|
|
128
|
+
try {
|
|
129
|
+
const [, collectionMemberID] = OnyxUtils_1.default.splitCollectionMemberKey(key);
|
|
130
|
+
if (skippableCollectionMemberIDs.has(collectionMemberID)) {
|
|
131
|
+
// The key is a skippable one, so we set the new value to null.
|
|
132
|
+
// eslint-disable-next-line no-param-reassign
|
|
133
|
+
value = null;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
catch (e) {
|
|
137
|
+
// The key is not a collection one or something went wrong during split, so we proceed with the function's logic.
|
|
138
|
+
}
|
|
139
|
+
}
|
|
125
140
|
// Onyx.set will ignore `undefined` values as inputs, therefore we can return early.
|
|
126
141
|
if (value === undefined) {
|
|
127
142
|
return Promise.resolve();
|
|
@@ -173,7 +188,25 @@ function set(key, value) {
|
|
|
173
188
|
* @param data object keyed by ONYXKEYS and the values to set
|
|
174
189
|
*/
|
|
175
190
|
function multiSet(data) {
|
|
176
|
-
|
|
191
|
+
let newData = data;
|
|
192
|
+
const skippableCollectionMemberIDs = OnyxUtils_1.default.getSkippableCollectionMemberIDs();
|
|
193
|
+
if (skippableCollectionMemberIDs.size) {
|
|
194
|
+
newData = Object.keys(newData).reduce((result, key) => {
|
|
195
|
+
try {
|
|
196
|
+
const [, collectionMemberID] = OnyxUtils_1.default.splitCollectionMemberKey(key);
|
|
197
|
+
// If the collection member key is a skippable one we set its value to null.
|
|
198
|
+
// eslint-disable-next-line no-param-reassign
|
|
199
|
+
result[key] = !skippableCollectionMemberIDs.has(collectionMemberID) ? newData[key] : null;
|
|
200
|
+
}
|
|
201
|
+
catch (_a) {
|
|
202
|
+
// The key is not a collection one or something went wrong during split, so we assign the data to result anyway.
|
|
203
|
+
// eslint-disable-next-line no-param-reassign
|
|
204
|
+
result[key] = newData[key];
|
|
205
|
+
}
|
|
206
|
+
return result;
|
|
207
|
+
}, {});
|
|
208
|
+
}
|
|
209
|
+
const keyValuePairsToSet = OnyxUtils_1.default.prepareKeyValuePairsForStorage(newData, true);
|
|
177
210
|
const updatePromises = keyValuePairsToSet.map(([key, value]) => {
|
|
178
211
|
const prevValue = OnyxCache_1.default.get(key, false);
|
|
179
212
|
// Update cache and optimistically inform subscribers on the next tick
|
|
@@ -181,9 +214,9 @@ function multiSet(data) {
|
|
|
181
214
|
return OnyxUtils_1.default.scheduleSubscriberUpdate(key, value, prevValue);
|
|
182
215
|
});
|
|
183
216
|
return storage_1.default.multiSet(keyValuePairsToSet)
|
|
184
|
-
.catch((error) => OnyxUtils_1.default.evictStorageAndRetry(error, multiSet,
|
|
217
|
+
.catch((error) => OnyxUtils_1.default.evictStorageAndRetry(error, multiSet, newData))
|
|
185
218
|
.then(() => {
|
|
186
|
-
OnyxUtils_1.default.sendActionToDevTools(OnyxUtils_1.default.METHOD.MULTI_SET, undefined,
|
|
219
|
+
OnyxUtils_1.default.sendActionToDevTools(OnyxUtils_1.default.METHOD.MULTI_SET, undefined, newData);
|
|
187
220
|
return Promise.all(updatePromises);
|
|
188
221
|
})
|
|
189
222
|
.then(() => undefined);
|
|
@@ -205,6 +238,20 @@ function multiSet(data) {
|
|
|
205
238
|
* Onyx.merge(ONYXKEYS.POLICY, {name: 'My Workspace'}); // -> {id: 1, name: 'My Workspace'}
|
|
206
239
|
*/
|
|
207
240
|
function merge(key, changes) {
|
|
241
|
+
const skippableCollectionMemberIDs = OnyxUtils_1.default.getSkippableCollectionMemberIDs();
|
|
242
|
+
if (skippableCollectionMemberIDs.size) {
|
|
243
|
+
try {
|
|
244
|
+
const [, collectionMemberID] = OnyxUtils_1.default.splitCollectionMemberKey(key);
|
|
245
|
+
if (skippableCollectionMemberIDs.has(collectionMemberID)) {
|
|
246
|
+
// The key is a skippable one, so we set the new changes to undefined.
|
|
247
|
+
// eslint-disable-next-line no-param-reassign
|
|
248
|
+
changes = undefined;
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
catch (e) {
|
|
252
|
+
// The key is not a collection one or something went wrong during split, so we proceed with the function's logic.
|
|
253
|
+
}
|
|
254
|
+
}
|
|
208
255
|
const mergeQueue = OnyxUtils_1.default.getMergeQueue();
|
|
209
256
|
const mergeQueuePromise = OnyxUtils_1.default.getMergeQueuePromise();
|
|
210
257
|
// Top-level undefined values are ignored
|
|
@@ -301,17 +348,35 @@ function mergeCollection(collectionKey, collection) {
|
|
|
301
348
|
Logger.logInfo('mergeCollection() called with invalid or empty value. Skipping this update.');
|
|
302
349
|
return Promise.resolve();
|
|
303
350
|
}
|
|
304
|
-
|
|
351
|
+
let resultCollection = collection;
|
|
352
|
+
let resultCollectionKeys = Object.keys(resultCollection);
|
|
305
353
|
// Confirm all the collection keys belong to the same parent
|
|
306
|
-
|
|
307
|
-
if (!OnyxUtils_1.default.doAllCollectionItemsBelongToSameParent(collectionKey, mergedCollectionKeys)) {
|
|
354
|
+
if (!OnyxUtils_1.default.doAllCollectionItemsBelongToSameParent(collectionKey, resultCollectionKeys)) {
|
|
308
355
|
return Promise.resolve();
|
|
309
356
|
}
|
|
357
|
+
const skippableCollectionMemberIDs = OnyxUtils_1.default.getSkippableCollectionMemberIDs();
|
|
358
|
+
if (skippableCollectionMemberIDs.size) {
|
|
359
|
+
resultCollection = resultCollectionKeys.reduce((result, key) => {
|
|
360
|
+
try {
|
|
361
|
+
const [, collectionMemberID] = OnyxUtils_1.default.splitCollectionMemberKey(key, collectionKey);
|
|
362
|
+
// If the collection member key is a skippable one we set its value to null.
|
|
363
|
+
// eslint-disable-next-line no-param-reassign
|
|
364
|
+
result[key] = !skippableCollectionMemberIDs.has(collectionMemberID) ? resultCollection[key] : null;
|
|
365
|
+
}
|
|
366
|
+
catch (_a) {
|
|
367
|
+
// Something went wrong during split, so we assign the data to result anyway.
|
|
368
|
+
// eslint-disable-next-line no-param-reassign
|
|
369
|
+
result[key] = resultCollection[key];
|
|
370
|
+
}
|
|
371
|
+
return result;
|
|
372
|
+
}, {});
|
|
373
|
+
}
|
|
374
|
+
resultCollectionKeys = Object.keys(resultCollection);
|
|
310
375
|
return OnyxUtils_1.default.getAllKeys()
|
|
311
376
|
.then((persistedKeys) => {
|
|
312
377
|
// Split to keys that exist in storage and keys that don't
|
|
313
|
-
const keys =
|
|
314
|
-
if (
|
|
378
|
+
const keys = resultCollectionKeys.filter((key) => {
|
|
379
|
+
if (resultCollection[key] === null) {
|
|
315
380
|
OnyxUtils_1.default.remove(key);
|
|
316
381
|
return false;
|
|
317
382
|
}
|
|
@@ -320,13 +385,13 @@ function mergeCollection(collectionKey, collection) {
|
|
|
320
385
|
const existingKeys = keys.filter((key) => persistedKeys.has(key));
|
|
321
386
|
const cachedCollectionForExistingKeys = OnyxUtils_1.default.getCachedCollection(collectionKey, existingKeys);
|
|
322
387
|
const existingKeyCollection = existingKeys.reduce((obj, key) => {
|
|
323
|
-
const { isCompatible, existingValueType, newValueType } = utils_1.default.checkCompatibilityWithExistingValue(
|
|
388
|
+
const { isCompatible, existingValueType, newValueType } = utils_1.default.checkCompatibilityWithExistingValue(resultCollection[key], cachedCollectionForExistingKeys[key]);
|
|
324
389
|
if (!isCompatible) {
|
|
325
390
|
Logger.logAlert(logMessages_1.default.incompatibleUpdateAlert(key, 'mergeCollection', existingValueType, newValueType));
|
|
326
391
|
return obj;
|
|
327
392
|
}
|
|
328
393
|
// eslint-disable-next-line no-param-reassign
|
|
329
|
-
obj[key] =
|
|
394
|
+
obj[key] = resultCollection[key];
|
|
330
395
|
return obj;
|
|
331
396
|
}, {});
|
|
332
397
|
const newCollection = {};
|
|
@@ -334,7 +399,7 @@ function mergeCollection(collectionKey, collection) {
|
|
|
334
399
|
if (persistedKeys.has(key)) {
|
|
335
400
|
return;
|
|
336
401
|
}
|
|
337
|
-
newCollection[key] =
|
|
402
|
+
newCollection[key] = resultCollection[key];
|
|
338
403
|
});
|
|
339
404
|
// When (multi-)merging the values with the existing values in storage,
|
|
340
405
|
// we don't want to remove nested null values from the data that we pass to the storage layer,
|
|
@@ -364,9 +429,9 @@ function mergeCollection(collectionKey, collection) {
|
|
|
364
429
|
return OnyxUtils_1.default.scheduleNotifyCollectionSubscribers(collectionKey, finalMergedCollection, previousCollection);
|
|
365
430
|
});
|
|
366
431
|
return Promise.all(promises)
|
|
367
|
-
.catch((error) => OnyxUtils_1.default.evictStorageAndRetry(error, mergeCollection, collectionKey,
|
|
432
|
+
.catch((error) => OnyxUtils_1.default.evictStorageAndRetry(error, mergeCollection, collectionKey, resultCollection))
|
|
368
433
|
.then(() => {
|
|
369
|
-
OnyxUtils_1.default.sendActionToDevTools(OnyxUtils_1.default.METHOD.MERGE_COLLECTION, undefined,
|
|
434
|
+
OnyxUtils_1.default.sendActionToDevTools(OnyxUtils_1.default.METHOD.MERGE_COLLECTION, undefined, resultCollection);
|
|
370
435
|
return promiseUpdate;
|
|
371
436
|
});
|
|
372
437
|
})
|
|
@@ -649,18 +714,38 @@ function update(data) {
|
|
|
649
714
|
* @param collection Object collection keyed by individual collection member keys and values
|
|
650
715
|
*/
|
|
651
716
|
function setCollection(collectionKey, collection) {
|
|
652
|
-
|
|
653
|
-
|
|
717
|
+
let resultCollection = collection;
|
|
718
|
+
let resultCollectionKeys = Object.keys(resultCollection);
|
|
719
|
+
// Confirm all the collection keys belong to the same parent
|
|
720
|
+
if (!OnyxUtils_1.default.doAllCollectionItemsBelongToSameParent(collectionKey, resultCollectionKeys)) {
|
|
654
721
|
Logger.logAlert(`setCollection called with keys that do not belong to the same parent ${collectionKey}. Skipping this update.`);
|
|
655
722
|
return Promise.resolve();
|
|
656
723
|
}
|
|
724
|
+
const skippableCollectionMemberIDs = OnyxUtils_1.default.getSkippableCollectionMemberIDs();
|
|
725
|
+
if (skippableCollectionMemberIDs.size) {
|
|
726
|
+
resultCollection = resultCollectionKeys.reduce((result, key) => {
|
|
727
|
+
try {
|
|
728
|
+
const [, collectionMemberID] = OnyxUtils_1.default.splitCollectionMemberKey(key, collectionKey);
|
|
729
|
+
// If the collection member key is a skippable one we set its value to null.
|
|
730
|
+
// eslint-disable-next-line no-param-reassign
|
|
731
|
+
result[key] = !skippableCollectionMemberIDs.has(collectionMemberID) ? resultCollection[key] : null;
|
|
732
|
+
}
|
|
733
|
+
catch (_a) {
|
|
734
|
+
// Something went wrong during split, so we assign the data to result anyway.
|
|
735
|
+
// eslint-disable-next-line no-param-reassign
|
|
736
|
+
result[key] = resultCollection[key];
|
|
737
|
+
}
|
|
738
|
+
return result;
|
|
739
|
+
}, {});
|
|
740
|
+
}
|
|
741
|
+
resultCollectionKeys = Object.keys(resultCollection);
|
|
657
742
|
return OnyxUtils_1.default.getAllKeys().then((persistedKeys) => {
|
|
658
|
-
const mutableCollection = Object.assign({},
|
|
743
|
+
const mutableCollection = Object.assign({}, resultCollection);
|
|
659
744
|
persistedKeys.forEach((key) => {
|
|
660
745
|
if (!key.startsWith(collectionKey)) {
|
|
661
746
|
return;
|
|
662
747
|
}
|
|
663
|
-
if (
|
|
748
|
+
if (resultCollectionKeys.includes(key)) {
|
|
664
749
|
return;
|
|
665
750
|
}
|
|
666
751
|
mutableCollection[key] = null;
|
package/dist/OnyxUtils.d.ts
CHANGED
|
@@ -32,6 +32,14 @@ declare function getDeferredInitTask(): DeferredTask;
|
|
|
32
32
|
* Getter - returns the eviction block list.
|
|
33
33
|
*/
|
|
34
34
|
declare function getEvictionBlocklist(): Record<OnyxKey, string[] | undefined>;
|
|
35
|
+
/**
|
|
36
|
+
* Getter - returns the skippable collection member IDs.
|
|
37
|
+
*/
|
|
38
|
+
declare function getSkippableCollectionMemberIDs(): Set<string>;
|
|
39
|
+
/**
|
|
40
|
+
* Setter - sets the skippable collection member IDs.
|
|
41
|
+
*/
|
|
42
|
+
declare function setSkippableCollectionMemberIDs(ids: Set<string>): void;
|
|
35
43
|
/**
|
|
36
44
|
* Sets the initial values for the Onyx store
|
|
37
45
|
*
|
|
@@ -76,10 +84,11 @@ declare function isCollectionMemberKey<TCollectionKey extends CollectionKeyBase>
|
|
|
76
84
|
/**
|
|
77
85
|
* Splits a collection member key into the collection key part and the ID part.
|
|
78
86
|
* @param key - The collection member key to split.
|
|
87
|
+
* @param collectionKey - The collection key of the `key` param that can be passed in advance to optimize the function.
|
|
79
88
|
* @returns A tuple where the first element is the collection part and the second element is the ID part,
|
|
80
89
|
* or throws an Error if the key is not a collection one.
|
|
81
90
|
*/
|
|
82
|
-
declare function splitCollectionMemberKey<TKey extends CollectionKey, CollectionKeyType = TKey extends `${infer Prefix}_${string}` ? `${Prefix}_` : never>(key: TKey): [CollectionKeyType, string];
|
|
91
|
+
declare function splitCollectionMemberKey<TKey extends CollectionKey, CollectionKeyType = TKey extends `${infer Prefix}_${string}` ? `${Prefix}_` : never>(key: TKey, collectionKey?: string): [CollectionKeyType, string];
|
|
83
92
|
/**
|
|
84
93
|
* Checks to see if a provided key is the exact configured key of our connected subscriber
|
|
85
94
|
* or if the provided key is a collection member key (in case our configured key is a "collection key")
|
|
@@ -277,6 +286,8 @@ declare const OnyxUtils: {
|
|
|
277
286
|
subscribeToKey: typeof subscribeToKey;
|
|
278
287
|
unsubscribeFromKey: typeof unsubscribeFromKey;
|
|
279
288
|
getEvictionBlocklist: typeof getEvictionBlocklist;
|
|
289
|
+
getSkippableCollectionMemberIDs: typeof getSkippableCollectionMemberIDs;
|
|
290
|
+
setSkippableCollectionMemberIDs: typeof setSkippableCollectionMemberIDs;
|
|
280
291
|
};
|
|
281
292
|
export type { OnyxMethod };
|
|
282
293
|
export default OnyxUtils;
|
package/dist/OnyxUtils.js
CHANGED
|
@@ -78,6 +78,8 @@ let snapshotKey = null;
|
|
|
78
78
|
let lastSubscriptionID = 0;
|
|
79
79
|
// Connections can be made before `Onyx.init`. They would wait for this task before resolving
|
|
80
80
|
const deferredInitTask = (0, createDeferredTask_1.default)();
|
|
81
|
+
// Holds a set of collection member IDs which updates will be ignored when using Onyx methods.
|
|
82
|
+
let skippableCollectionMemberIDs = new Set();
|
|
81
83
|
function getSnapshotKey() {
|
|
82
84
|
return snapshotKey;
|
|
83
85
|
}
|
|
@@ -111,6 +113,18 @@ function getDeferredInitTask() {
|
|
|
111
113
|
function getEvictionBlocklist() {
|
|
112
114
|
return evictionBlocklist;
|
|
113
115
|
}
|
|
116
|
+
/**
|
|
117
|
+
* Getter - returns the skippable collection member IDs.
|
|
118
|
+
*/
|
|
119
|
+
function getSkippableCollectionMemberIDs() {
|
|
120
|
+
return skippableCollectionMemberIDs;
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Setter - sets the skippable collection member IDs.
|
|
124
|
+
*/
|
|
125
|
+
function setSkippableCollectionMemberIDs(ids) {
|
|
126
|
+
skippableCollectionMemberIDs = ids;
|
|
127
|
+
}
|
|
114
128
|
/**
|
|
115
129
|
* Sets the initial values for the Onyx store
|
|
116
130
|
*
|
|
@@ -198,6 +212,19 @@ function get(key) {
|
|
|
198
212
|
// Otherwise retrieve the value from storage and capture a promise to aid concurrent usages
|
|
199
213
|
const promise = storage_1.default.getItem(key)
|
|
200
214
|
.then((val) => {
|
|
215
|
+
if (skippableCollectionMemberIDs.size) {
|
|
216
|
+
try {
|
|
217
|
+
const [, collectionMemberID] = splitCollectionMemberKey(key);
|
|
218
|
+
if (skippableCollectionMemberIDs.has(collectionMemberID)) {
|
|
219
|
+
// The key is a skippable one, so we set the value to undefined.
|
|
220
|
+
// eslint-disable-next-line no-param-reassign
|
|
221
|
+
val = undefined;
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
catch (e) {
|
|
225
|
+
// The key is not a collection one or something went wrong during split, so we proceed with the function's logic.
|
|
226
|
+
}
|
|
227
|
+
}
|
|
201
228
|
if (val === undefined) {
|
|
202
229
|
OnyxCache_1.default.addNullishStorageKey(key);
|
|
203
230
|
return undefined;
|
|
@@ -264,6 +291,18 @@ function multiGet(keys) {
|
|
|
264
291
|
// temp object is used to merge the missing data into the cache
|
|
265
292
|
const temp = {};
|
|
266
293
|
values.forEach(([key, value]) => {
|
|
294
|
+
if (skippableCollectionMemberIDs.size) {
|
|
295
|
+
try {
|
|
296
|
+
const [, collectionMemberID] = OnyxUtils.splitCollectionMemberKey(key);
|
|
297
|
+
if (skippableCollectionMemberIDs.has(collectionMemberID)) {
|
|
298
|
+
// The key is a skippable one, so we skip this iteration.
|
|
299
|
+
return;
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
catch (e) {
|
|
303
|
+
// The key is not a collection one or something went wrong during split, so we proceed with the function's logic.
|
|
304
|
+
}
|
|
305
|
+
}
|
|
267
306
|
dataMap.set(key, value);
|
|
268
307
|
temp[key] = value;
|
|
269
308
|
});
|
|
@@ -334,11 +373,18 @@ function isCollectionMemberKey(collectionKey, key, collectionKeyLength) {
|
|
|
334
373
|
/**
|
|
335
374
|
* Splits a collection member key into the collection key part and the ID part.
|
|
336
375
|
* @param key - The collection member key to split.
|
|
376
|
+
* @param collectionKey - The collection key of the `key` param that can be passed in advance to optimize the function.
|
|
337
377
|
* @returns A tuple where the first element is the collection part and the second element is the ID part,
|
|
338
378
|
* or throws an Error if the key is not a collection one.
|
|
339
379
|
*/
|
|
340
|
-
function splitCollectionMemberKey(key) {
|
|
341
|
-
|
|
380
|
+
function splitCollectionMemberKey(key, collectionKey) {
|
|
381
|
+
if (collectionKey && !isCollectionMemberKey(collectionKey, key, collectionKey.length)) {
|
|
382
|
+
throw new Error(`Invalid '${collectionKey}' collection key provided, it isn't compatible with '${key}' key.`);
|
|
383
|
+
}
|
|
384
|
+
if (!collectionKey) {
|
|
385
|
+
// eslint-disable-next-line no-param-reassign
|
|
386
|
+
collectionKey = getCollectionKey(key);
|
|
387
|
+
}
|
|
342
388
|
return [collectionKey, key.slice(collectionKey.length)];
|
|
343
389
|
}
|
|
344
390
|
/**
|
|
@@ -1162,6 +1208,8 @@ const OnyxUtils = {
|
|
|
1162
1208
|
subscribeToKey,
|
|
1163
1209
|
unsubscribeFromKey,
|
|
1164
1210
|
getEvictionBlocklist,
|
|
1211
|
+
getSkippableCollectionMemberIDs,
|
|
1212
|
+
setSkippableCollectionMemberIDs,
|
|
1165
1213
|
};
|
|
1166
1214
|
GlobalSettings.addGlobalSettingsChangeListener(({ enablePerformanceMetrics }) => {
|
|
1167
1215
|
if (!enablePerformanceMetrics) {
|
package/dist/types.d.ts
CHANGED
|
@@ -398,6 +398,11 @@ type InitOptions = {
|
|
|
398
398
|
* @default false
|
|
399
399
|
*/
|
|
400
400
|
enablePerformanceMetrics?: boolean;
|
|
401
|
+
/**
|
|
402
|
+
* Array of collection member IDs which updates will be ignored when using Onyx methods.
|
|
403
|
+
* Additionally, any subscribers from these keys to won't receive any data from Onyx.
|
|
404
|
+
*/
|
|
405
|
+
skippableCollectionMemberIDs?: string[];
|
|
401
406
|
};
|
|
402
407
|
type GenericFunction = (...args: any[]) => any;
|
|
403
408
|
/**
|
package/dist/useOnyx.d.ts
CHANGED
|
@@ -18,6 +18,10 @@ type BaseUseOnyxOptions = {
|
|
|
18
18
|
* with the same connect configurations.
|
|
19
19
|
*/
|
|
20
20
|
reuseConnection?: boolean;
|
|
21
|
+
/**
|
|
22
|
+
* If set to `true`, the key can be changed dynamically during the component lifecycle.
|
|
23
|
+
*/
|
|
24
|
+
allowDynamicKey?: boolean;
|
|
21
25
|
};
|
|
22
26
|
type UseOnyxInitialValueOption<TInitialValue> = {
|
|
23
27
|
/**
|
|
@@ -36,6 +40,7 @@ type UseOnyxSelectorOption<TKey extends OnyxKey, TReturnValue> = {
|
|
|
36
40
|
*/
|
|
37
41
|
selector?: UseOnyxSelector<TKey, TReturnValue>;
|
|
38
42
|
};
|
|
43
|
+
type UseOnyxOptions<TKey extends OnyxKey, TReturnValue> = BaseUseOnyxOptions & UseOnyxInitialValueOption<TReturnValue> & UseOnyxSelectorOption<TKey, TReturnValue>;
|
|
39
44
|
type FetchStatus = 'loading' | 'loaded';
|
|
40
45
|
type ResultMetadata = {
|
|
41
46
|
status: FetchStatus;
|
|
@@ -44,4 +49,4 @@ type UseOnyxResult<TValue> = [NonNullable<TValue> | undefined, ResultMetadata];
|
|
|
44
49
|
declare function useOnyx<TKey extends OnyxKey, TReturnValue = OnyxValue<TKey>>(key: TKey, options?: BaseUseOnyxOptions & UseOnyxInitialValueOption<TReturnValue> & Required<UseOnyxSelectorOption<TKey, TReturnValue>>, dependencies?: DependencyList): UseOnyxResult<TReturnValue>;
|
|
45
50
|
declare function useOnyx<TKey extends OnyxKey, TReturnValue = OnyxValue<TKey>>(key: TKey, options?: BaseUseOnyxOptions & UseOnyxInitialValueOption<NoInfer<TReturnValue>>, dependencies?: DependencyList): UseOnyxResult<TReturnValue>;
|
|
46
51
|
export default useOnyx;
|
|
47
|
-
export type { FetchStatus, ResultMetadata, UseOnyxResult };
|
|
52
|
+
export type { FetchStatus, ResultMetadata, UseOnyxResult, BaseUseOnyxOptions, UseOnyxSelector, UseOnyxSelectorOption, UseOnyxInitialValueOption, UseOnyxOptions };
|
package/dist/useOnyx.js
CHANGED
|
@@ -96,7 +96,7 @@ function useOnyx(key, options, dependencies = []) {
|
|
|
96
96
|
const shouldGetCachedValueRef = (0, react_1.useRef)(true);
|
|
97
97
|
(0, react_1.useEffect)(() => {
|
|
98
98
|
// These conditions will ensure we can only handle dynamic collection member keys from the same collection.
|
|
99
|
-
if (previousKey === key) {
|
|
99
|
+
if ((options === null || options === void 0 ? void 0 : options.allowDynamicKey) || previousKey === key) {
|
|
100
100
|
return;
|
|
101
101
|
}
|
|
102
102
|
try {
|
|
@@ -112,7 +112,7 @@ function useOnyx(key, options, dependencies = []) {
|
|
|
112
112
|
throw new Error(`'${previousKey}' key can't be changed to '${key}'. useOnyx() only supports dynamic keys if they are both collection member keys from the same collection e.g. from 'collection_id1' to 'collection_id2'.`);
|
|
113
113
|
}
|
|
114
114
|
throw new Error(`'${previousKey}' key can't be changed to '${key}'. useOnyx() only supports dynamic keys if they are both collection member keys from the same collection e.g. from 'collection_id1' to 'collection_id2'.`);
|
|
115
|
-
}, [previousKey, key]);
|
|
115
|
+
}, [previousKey, key, options === null || options === void 0 ? void 0 : options.allowDynamicKey]);
|
|
116
116
|
(0, react_1.useEffect)(() => {
|
|
117
117
|
// This effect will only run if the `dependencies` array changes. If it changes it will force the hook
|
|
118
118
|
// to trigger a `getSnapshot()` update by calling the stored `onStoreChange()` function reference, thus
|