react-native-onyx 3.0.37 → 3.0.39
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/README.md +0 -15
- package/dist/Onyx.js +1 -8
- package/dist/OnyxCache.d.ts +1 -1
- package/dist/OnyxCache.js +1 -1
- package/dist/OnyxSnapshotCache.d.ts +1 -2
- package/dist/OnyxSnapshotCache.js +5 -10
- package/dist/OnyxUtils.d.ts +2 -2
- package/dist/OnyxUtils.js +13 -26
- package/dist/useOnyx.d.ts +0 -7
- package/dist/useOnyx.js +2 -14
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -206,21 +206,6 @@ export default App;
|
|
|
206
206
|
|
|
207
207
|
It's also beneficial to use a [selector](https://github.com/Expensify/react-native-onyx/blob/main/API.md#connectmapping--number) with the mapping in case you need to grab a single item in a collection (like a single report action).
|
|
208
208
|
|
|
209
|
-
### useOnyx()'s `canBeMissing` option
|
|
210
|
-
|
|
211
|
-
You must pass the `canBeMissing` configuration flag to `useOnyx` if you want the hook to log an alert when data is missing from Onyx store. Regarding usage in `Expensify/App` repo, if the component calling this is the one loading the data by calling an action, then you should set this to `true`. If the component calling this does not load the data then you should set it to `false`, which means that if the data is not there, it will log an alert, as it means we are using data that no one loaded and that's most probably a bug.
|
|
212
|
-
|
|
213
|
-
```javascript
|
|
214
|
-
const Component = ({reportID}) => {
|
|
215
|
-
// This hook will log an alert (via `Logger.logAlert()`) if `report` is `undefined`.
|
|
216
|
-
const [report] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${reportID}`, {canBeMissing: false});
|
|
217
|
-
|
|
218
|
-
// rest of the component's code.
|
|
219
|
-
};
|
|
220
|
-
|
|
221
|
-
export default Component;
|
|
222
|
-
```
|
|
223
|
-
|
|
224
209
|
## Collections
|
|
225
210
|
|
|
226
211
|
Collections allow keys with similar value types to be subscribed together by subscribing to the collection key. To define one, it must be included in the `ONYXKEYS.COLLECTION` object and it must be suffixed with an underscore. Member keys should use a unique identifier or index after the collection key prefix (e.g. `report_42`).
|
package/dist/Onyx.js
CHANGED
|
@@ -317,14 +317,7 @@ function clear(keysToPreserve = []) {
|
|
|
317
317
|
const newValue = (_a = defaultKeyStates[key]) !== null && _a !== void 0 ? _a : null;
|
|
318
318
|
if (newValue !== oldValue) {
|
|
319
319
|
OnyxCache_1.default.set(key, newValue);
|
|
320
|
-
|
|
321
|
-
try {
|
|
322
|
-
collectionKey = OnyxUtils_1.default.getCollectionKey(key);
|
|
323
|
-
}
|
|
324
|
-
catch (e) {
|
|
325
|
-
// If getCollectionKey() throws an error it means the key is not a collection key.
|
|
326
|
-
collectionKey = undefined;
|
|
327
|
-
}
|
|
320
|
+
const collectionKey = OnyxUtils_1.default.getCollectionKey(key);
|
|
328
321
|
if (collectionKey) {
|
|
329
322
|
if (!keyValuesToResetAsCollection[collectionKey]) {
|
|
330
323
|
keyValuesToResetAsCollection[collectionKey] = { oldValues: {}, newValues: {} };
|
package/dist/OnyxCache.d.ts
CHANGED
|
@@ -162,7 +162,7 @@ declare class OnyxCache {
|
|
|
162
162
|
/**
|
|
163
163
|
* Get the collection key for a given member key
|
|
164
164
|
*/
|
|
165
|
-
getCollectionKey(key: OnyxKey): OnyxKey |
|
|
165
|
+
getCollectionKey(key: OnyxKey): OnyxKey | undefined;
|
|
166
166
|
/**
|
|
167
167
|
* Get all data for a collection key
|
|
168
168
|
*/
|
package/dist/OnyxCache.js
CHANGED
|
@@ -40,12 +40,11 @@ declare class OnyxSnapshotCache {
|
|
|
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
42
|
* - `allowStaleData`: Controls whether stale data can be returned during pending merges, affecting result timing
|
|
43
|
-
* - `canBeMissing`: Determines logging behavior for missing data, but doesn't affect the actual data returned
|
|
44
43
|
*
|
|
45
44
|
* Other options like `canEvict`, `reuseConnection`, and `allowDynamicKey` don't affect the data transformation
|
|
46
45
|
* or timing behavior of getSnapshot, so they're excluded from the cache key for better cache hit rates.
|
|
47
46
|
*/
|
|
48
|
-
registerConsumer<TKey extends OnyxKey, TReturnValue>(options: Pick<UseOnyxOptions<TKey, TReturnValue>, 'selector' | 'initWithStoredValues' | 'allowStaleData'
|
|
47
|
+
registerConsumer<TKey extends OnyxKey, TReturnValue>(options: Pick<UseOnyxOptions<TKey, TReturnValue>, 'selector' | 'initWithStoredValues' | 'allowStaleData'>): string;
|
|
49
48
|
/**
|
|
50
49
|
* Deregister a consumer for a cache key.
|
|
51
50
|
* Decrements reference counter and removes cache entry if no consumers remain.
|
|
@@ -37,19 +37,17 @@ class OnyxSnapshotCache {
|
|
|
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
39
|
* - `allowStaleData`: Controls whether stale data can be returned during pending merges, affecting result timing
|
|
40
|
-
* - `canBeMissing`: Determines logging behavior for missing data, but doesn't affect the actual data returned
|
|
41
40
|
*
|
|
42
41
|
* Other options like `canEvict`, `reuseConnection`, and `allowDynamicKey` don't affect the data transformation
|
|
43
42
|
* or timing behavior of getSnapshot, so they're excluded from the cache key for better cache hit rates.
|
|
44
43
|
*/
|
|
45
44
|
registerConsumer(options) {
|
|
46
|
-
var _a, _b
|
|
45
|
+
var _a, _b;
|
|
47
46
|
const selectorID = (options === null || options === void 0 ? void 0 : options.selector) ? this.getSelectorID(options.selector) : 'no_selector';
|
|
48
47
|
// Create options hash without expensive JSON.stringify
|
|
49
48
|
const initWithStoredValues = (_a = options === null || options === void 0 ? void 0 : options.initWithStoredValues) !== null && _a !== void 0 ? _a : true;
|
|
50
49
|
const allowStaleData = (_b = options === null || options === void 0 ? void 0 : options.allowStaleData) !== null && _b !== void 0 ? _b : false;
|
|
51
|
-
const
|
|
52
|
-
const cacheKey = `${selectorID}_${initWithStoredValues}_${allowStaleData}_${canBeMissing}`;
|
|
50
|
+
const cacheKey = `${selectorID}_${initWithStoredValues}_${allowStaleData}`;
|
|
53
51
|
// Increment reference count for this cache key
|
|
54
52
|
const currentCount = this.cacheKeyRefCounts.get(cacheKey) || 0;
|
|
55
53
|
this.cacheKeyRefCounts.set(cacheKey, currentCount + 1);
|
|
@@ -102,14 +100,11 @@ class OnyxSnapshotCache {
|
|
|
102
100
|
invalidateForKey(keyToInvalidate) {
|
|
103
101
|
// Always invalidate the exact key
|
|
104
102
|
this.snapshotCache.delete(keyToInvalidate);
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
103
|
+
// Check if the key is a collection member and invalidate the collection base key
|
|
104
|
+
const collectionBaseKey = OnyxUtils_1.default.getCollectionKey(keyToInvalidate);
|
|
105
|
+
if (collectionBaseKey) {
|
|
108
106
|
this.snapshotCache.delete(collectionBaseKey);
|
|
109
107
|
}
|
|
110
|
-
catch (e) {
|
|
111
|
-
// do nothing - this just means the key is not a collection member
|
|
112
|
-
}
|
|
113
108
|
}
|
|
114
109
|
/**
|
|
115
110
|
* Clear all snapshot cache
|
package/dist/OnyxUtils.d.ts
CHANGED
|
@@ -163,9 +163,9 @@ declare function isKeyMatch(configKey: OnyxKey, key: OnyxKey): boolean;
|
|
|
163
163
|
* - `getCollectionKey("sharedNVP_user_-1_something")` would return "sharedNVP_user_"
|
|
164
164
|
*
|
|
165
165
|
* @param key - The collection key to process.
|
|
166
|
-
* @returns The plain collection key or
|
|
166
|
+
* @returns The plain collection key or undefined if the key is not a collection one.
|
|
167
167
|
*/
|
|
168
|
-
declare function getCollectionKey(key: CollectionKey): string;
|
|
168
|
+
declare function getCollectionKey(key: CollectionKey): string | undefined;
|
|
169
169
|
/**
|
|
170
170
|
* Tries to get a value from the cache. If the value is not present in cache it will return the default value or undefined.
|
|
171
171
|
* If the requested key is a collection, it will return an object with all the collection members.
|
package/dist/OnyxUtils.js
CHANGED
|
@@ -389,15 +389,9 @@ function isCollectionMemberKey(collectionKey, key) {
|
|
|
389
389
|
* @returns true if the key is a collection member, false otherwise
|
|
390
390
|
*/
|
|
391
391
|
function isCollectionMember(key) {
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
return key.length > collectionKey.length;
|
|
396
|
-
}
|
|
397
|
-
catch (e) {
|
|
398
|
-
// If getCollectionKey throws, the key is not a collection member
|
|
399
|
-
return false;
|
|
400
|
-
}
|
|
392
|
+
const collectionKey = getCollectionKey(key);
|
|
393
|
+
// If the key is longer than the collection key, it's a collection member
|
|
394
|
+
return !!collectionKey && key.length > collectionKey.length;
|
|
401
395
|
}
|
|
402
396
|
/**
|
|
403
397
|
* Checks if a given key is a RAM-only key, RAM-only collection key, or a RAM-only collection member
|
|
@@ -417,14 +411,10 @@ function isCollectionMember(key) {
|
|
|
417
411
|
* @returns true if key is a RAM-only key, RAM-only collection key, or a RAM-only collection member
|
|
418
412
|
*/
|
|
419
413
|
function isRamOnlyKey(key) {
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
// If collectionKey exists for a given key, check if it's a RAM-only key
|
|
414
|
+
const collectionKey = getCollectionKey(key);
|
|
415
|
+
if (collectionKey) {
|
|
423
416
|
return OnyxCache_1.default.isRamOnlyKey(collectionKey);
|
|
424
417
|
}
|
|
425
|
-
catch (_a) {
|
|
426
|
-
// If getCollectionKey throws, the key is not a collection member
|
|
427
|
-
}
|
|
428
418
|
return OnyxCache_1.default.isRamOnlyKey(key);
|
|
429
419
|
}
|
|
430
420
|
/**
|
|
@@ -439,8 +429,12 @@ function splitCollectionMemberKey(key, collectionKey) {
|
|
|
439
429
|
throw new Error(`Invalid '${collectionKey}' collection key provided, it isn't compatible with '${key}' key.`);
|
|
440
430
|
}
|
|
441
431
|
if (!collectionKey) {
|
|
432
|
+
const resolvedKey = getCollectionKey(key);
|
|
433
|
+
if (!resolvedKey) {
|
|
434
|
+
throw new Error(`Invalid '${key}' key provided, only collection keys are allowed.`);
|
|
435
|
+
}
|
|
442
436
|
// eslint-disable-next-line no-param-reassign
|
|
443
|
-
collectionKey =
|
|
437
|
+
collectionKey = resolvedKey;
|
|
444
438
|
}
|
|
445
439
|
return [collectionKey, key.slice(collectionKey.length)];
|
|
446
440
|
}
|
|
@@ -461,7 +455,7 @@ function isKeyMatch(configKey, key) {
|
|
|
461
455
|
* - `getCollectionKey("sharedNVP_user_-1_something")` would return "sharedNVP_user_"
|
|
462
456
|
*
|
|
463
457
|
* @param key - The collection key to process.
|
|
464
|
-
* @returns The plain collection key or
|
|
458
|
+
* @returns The plain collection key or undefined if the key is not a collection one.
|
|
465
459
|
*/
|
|
466
460
|
function getCollectionKey(key) {
|
|
467
461
|
// Start by finding the position of the last underscore in the string
|
|
@@ -477,7 +471,7 @@ function getCollectionKey(key) {
|
|
|
477
471
|
// Move to the next underscore to check smaller possible keys
|
|
478
472
|
lastUnderscoreIndex = key.lastIndexOf('_', lastUnderscoreIndex - 1);
|
|
479
473
|
}
|
|
480
|
-
|
|
474
|
+
return undefined;
|
|
481
475
|
}
|
|
482
476
|
/**
|
|
483
477
|
* Tries to get a value from the cache. If the value is not present in cache it will return the default value or undefined.
|
|
@@ -625,14 +619,7 @@ function keyChanged(key, value, canUpdateSubscriber = () => true, isProcessingCo
|
|
|
625
619
|
// do the same in keysChanged, because we only call that function when a collection key changes, and it doesn't happen that often.
|
|
626
620
|
// For performance reason, we look for the given key and later if don't find it we look for the collection key, instead of checking if it is a collection key first.
|
|
627
621
|
let stateMappingKeys = (_a = onyxKeyToSubscriptionIDs.get(key)) !== null && _a !== void 0 ? _a : [];
|
|
628
|
-
|
|
629
|
-
try {
|
|
630
|
-
collectionKey = getCollectionKey(key);
|
|
631
|
-
}
|
|
632
|
-
catch (e) {
|
|
633
|
-
// If getCollectionKey() throws an error it means the key is not a collection key.
|
|
634
|
-
collectionKey = undefined;
|
|
635
|
-
}
|
|
622
|
+
const collectionKey = getCollectionKey(key);
|
|
636
623
|
if (collectionKey) {
|
|
637
624
|
// Getting the collection key from the specific key because only collection keys were stored in the mapping.
|
|
638
625
|
stateMappingKeys = [...stateMappingKeys, ...((_b = onyxKeyToSubscriptionIDs.get(collectionKey)) !== null && _b !== void 0 ? _b : [])];
|
package/dist/useOnyx.d.ts
CHANGED
|
@@ -24,13 +24,6 @@ type UseOnyxOptions<TKey extends OnyxKey, TReturnValue> = {
|
|
|
24
24
|
* If set to `true`, the key can be changed dynamically during the component lifecycle.
|
|
25
25
|
*/
|
|
26
26
|
allowDynamicKey?: boolean;
|
|
27
|
-
/**
|
|
28
|
-
* If the component calling this is the one loading the data by calling an action, then you should set this to `true`.
|
|
29
|
-
*
|
|
30
|
-
* If the component calling this does not load the data then you should set it to `false`, which means that if the data
|
|
31
|
-
* is not there, it will log an alert, as it means we are using data that no one loaded and that's most probably a bug.
|
|
32
|
-
*/
|
|
33
|
-
canBeMissing?: boolean;
|
|
34
27
|
/**
|
|
35
28
|
* This will be used to subscribe to a subset of an Onyx key's data.
|
|
36
29
|
* Using this setting on `useOnyx` can have very positive performance benefits because the component will only re-render
|
package/dist/useOnyx.js
CHANGED
|
@@ -44,7 +44,6 @@ const OnyxUtils_1 = __importDefault(require("./OnyxUtils"));
|
|
|
44
44
|
const GlobalSettings = __importStar(require("./GlobalSettings"));
|
|
45
45
|
const usePrevious_1 = __importDefault(require("./usePrevious"));
|
|
46
46
|
const metrics_1 = __importDefault(require("./metrics"));
|
|
47
|
-
const Logger = __importStar(require("./Logger"));
|
|
48
47
|
const OnyxSnapshotCache_1 = __importDefault(require("./OnyxSnapshotCache"));
|
|
49
48
|
const useLiveRef_1 = __importDefault(require("./useLiveRef"));
|
|
50
49
|
function useOnyx(key, options, dependencies = []) {
|
|
@@ -111,8 +110,7 @@ function useOnyx(key, options, dependencies = []) {
|
|
|
111
110
|
selector: options === null || options === void 0 ? void 0 : options.selector,
|
|
112
111
|
initWithStoredValues: options === null || options === void 0 ? void 0 : options.initWithStoredValues,
|
|
113
112
|
allowStaleData: options === null || options === void 0 ? void 0 : options.allowStaleData,
|
|
114
|
-
|
|
115
|
-
}), [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, options === null || options === void 0 ? void 0 : options.canBeMissing]);
|
|
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]);
|
|
116
114
|
(0, react_1.useEffect)(() => () => OnyxSnapshotCache_1.default.deregisterConsumer(key, cacheKey), [key, cacheKey]);
|
|
117
115
|
(0, react_1.useEffect)(() => {
|
|
118
116
|
// These conditions will ensure we can only handle dynamic collection member keys from the same collection.
|
|
@@ -178,7 +176,6 @@ function useOnyx(key, options, dependencies = []) {
|
|
|
178
176
|
return cachedResult;
|
|
179
177
|
}
|
|
180
178
|
}
|
|
181
|
-
let isOnyxValueDefined = true;
|
|
182
179
|
// We return the initial result right away during the first connection if `initWithStoredValues` is set to `false`.
|
|
183
180
|
if (isFirstConnectionRef.current && (options === null || options === void 0 ? void 0 : options.initWithStoredValues) === false) {
|
|
184
181
|
const result = resultRef.current;
|
|
@@ -194,9 +191,6 @@ function useOnyx(key, options, dependencies = []) {
|
|
|
194
191
|
const value = OnyxUtils_1.default.tryGetCachedValue(key);
|
|
195
192
|
const selectedValue = memoizedSelector ? memoizedSelector(value) : value;
|
|
196
193
|
newValueRef.current = (selectedValue !== null && selectedValue !== void 0 ? selectedValue : undefined);
|
|
197
|
-
// This flag is `false` when the original Onyx value (without selector) is not defined yet.
|
|
198
|
-
// It will be used later to check if we need to log an alert that the value is missing.
|
|
199
|
-
isOnyxValueDefined = value !== null && value !== undefined;
|
|
200
194
|
// We set this flag to `false` again since we don't want to get the newest cached value every time `getSnapshot()` is executed,
|
|
201
195
|
// and only when `Onyx.connect()` callback is fired.
|
|
202
196
|
shouldGetCachedValueRef.current = false;
|
|
@@ -243,18 +237,12 @@ function useOnyx(key, options, dependencies = []) {
|
|
|
243
237
|
sourceValue: sourceValueRef.current,
|
|
244
238
|
},
|
|
245
239
|
];
|
|
246
|
-
// If `canBeMissing` is set to `false` and the Onyx value of that key is not defined,
|
|
247
|
-
// we log an alert so it can be acknowledged by the consumer. Additionally, we won't log alerts
|
|
248
|
-
// if there's a `Onyx.clear()` task in progress.
|
|
249
|
-
if ((options === null || options === void 0 ? void 0 : options.canBeMissing) === false && newFetchStatus === 'loaded' && !isOnyxValueDefined && !OnyxCache_1.default.hasPendingTask(OnyxCache_1.TASK.CLEAR)) {
|
|
250
|
-
Logger.logAlert(`useOnyx returned no data for key with canBeMissing set to false for key ${key}`, { showAlert: true });
|
|
251
|
-
}
|
|
252
240
|
}
|
|
253
241
|
if (newFetchStatus !== 'loading') {
|
|
254
242
|
OnyxSnapshotCache_1.default.setCachedResult(key, cacheKey, resultRef.current);
|
|
255
243
|
}
|
|
256
244
|
return resultRef.current;
|
|
257
|
-
}, [options === null || options === void 0 ? void 0 : options.initWithStoredValues, options === null || options === void 0 ? void 0 : options.allowStaleData,
|
|
245
|
+
}, [options === null || options === void 0 ? void 0 : options.initWithStoredValues, options === null || options === void 0 ? void 0 : options.allowStaleData, key, memoizedSelector, cacheKey, previousKey]);
|
|
258
246
|
const subscribe = (0, react_1.useCallback)((onStoreChange) => {
|
|
259
247
|
isConnectingRef.current = true;
|
|
260
248
|
onStoreChangeFnRef.current = onStoreChange;
|