react-native-onyx 2.0.94 → 2.0.95
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 +15 -0
- package/dist/Logger.d.ts +5 -3
- package/dist/Logger.js +6 -6
- package/dist/OnyxUtils.d.ts +1 -1
- package/dist/OnyxUtils.js +1 -1
- package/dist/useOnyx.d.ts +7 -0
- package/dist/useOnyx.js +22 -20
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -256,6 +256,21 @@ DO NOT use more than one `withOnyx` component at a time. It adds overhead and pr
|
|
|
256
256
|
|
|
257
257
|
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).
|
|
258
258
|
|
|
259
|
+
### useOnyx()'s `canBeMissing` option
|
|
260
|
+
|
|
261
|
+
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.
|
|
262
|
+
|
|
263
|
+
```javascript
|
|
264
|
+
const Component = ({reportID}) => {
|
|
265
|
+
// This hook will log an alert (via `Logger.logAlert()`) if `report` is `undefined`.
|
|
266
|
+
const [report] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${reportID}`, {canBeMissing: false});
|
|
267
|
+
|
|
268
|
+
// rest of the component's code.
|
|
269
|
+
};
|
|
270
|
+
|
|
271
|
+
export default Component;
|
|
272
|
+
```
|
|
273
|
+
|
|
259
274
|
## Collections
|
|
260
275
|
|
|
261
276
|
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/Logger.d.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
|
+
type Parameters = string | Record<string, unknown> | Array<Record<string, unknown>> | Error;
|
|
1
2
|
type LogData = {
|
|
2
3
|
message: string;
|
|
3
4
|
level: 'alert' | 'info' | 'hmmm';
|
|
5
|
+
parameters?: Parameters;
|
|
4
6
|
};
|
|
5
7
|
type LoggerCallback = (data: LogData) => void;
|
|
6
8
|
/**
|
|
@@ -10,13 +12,13 @@ declare function registerLogger(callback: LoggerCallback): void;
|
|
|
10
12
|
/**
|
|
11
13
|
* Send an alert message to the logger
|
|
12
14
|
*/
|
|
13
|
-
declare function logAlert(message: string): void;
|
|
15
|
+
declare function logAlert(message: string, parameters?: Parameters): void;
|
|
14
16
|
/**
|
|
15
17
|
* Send an info message to the logger
|
|
16
18
|
*/
|
|
17
|
-
declare function logInfo(message: string): void;
|
|
19
|
+
declare function logInfo(message: string, parameters?: Parameters): void;
|
|
18
20
|
/**
|
|
19
21
|
* Send an hmmm message to the logger
|
|
20
22
|
*/
|
|
21
|
-
declare function logHmmm(message: string): void;
|
|
23
|
+
declare function logHmmm(message: string, parameters?: Parameters): void;
|
|
22
24
|
export { registerLogger, logInfo, logAlert, logHmmm };
|
package/dist/Logger.js
CHANGED
|
@@ -13,21 +13,21 @@ exports.registerLogger = registerLogger;
|
|
|
13
13
|
/**
|
|
14
14
|
* Send an alert message to the logger
|
|
15
15
|
*/
|
|
16
|
-
function logAlert(message) {
|
|
17
|
-
logger({ message: `[Onyx] ${message}`, level: 'alert' });
|
|
16
|
+
function logAlert(message, parameters) {
|
|
17
|
+
logger({ message: `[Onyx] ${message}`, level: 'alert', parameters });
|
|
18
18
|
}
|
|
19
19
|
exports.logAlert = logAlert;
|
|
20
20
|
/**
|
|
21
21
|
* Send an info message to the logger
|
|
22
22
|
*/
|
|
23
|
-
function logInfo(message) {
|
|
24
|
-
logger({ message: `[Onyx] ${message}`, level: 'info' });
|
|
23
|
+
function logInfo(message, parameters) {
|
|
24
|
+
logger({ message: `[Onyx] ${message}`, level: 'info', parameters });
|
|
25
25
|
}
|
|
26
26
|
exports.logInfo = logInfo;
|
|
27
27
|
/**
|
|
28
28
|
* Send an hmmm message to the logger
|
|
29
29
|
*/
|
|
30
|
-
function logHmmm(message) {
|
|
31
|
-
logger({ message: `[Onyx] ${message}`, level: 'hmmm' });
|
|
30
|
+
function logHmmm(message, parameters) {
|
|
31
|
+
logger({ message: `[Onyx] ${message}`, level: 'hmmm', parameters });
|
|
32
32
|
}
|
|
33
33
|
exports.logHmmm = logHmmm;
|
package/dist/OnyxUtils.d.ts
CHANGED
|
@@ -73,7 +73,7 @@ declare function multiGet<TKey extends OnyxKey>(keys: CollectionKeyBase[]): Prom
|
|
|
73
73
|
* This helper exists to map an array of Onyx keys such as `['report_', 'conciergeReportID']`
|
|
74
74
|
* to the values for those keys (correctly typed) such as `[OnyxCollection<Report>, OnyxEntry<string>]`
|
|
75
75
|
*
|
|
76
|
-
* Note: just using
|
|
76
|
+
* Note: just using `.map`, you'd end up with `Array<OnyxCollection<Report>|OnyxEntry<string>>`, which is not what we want. This preserves the order of the keys provided.
|
|
77
77
|
*/
|
|
78
78
|
declare function tupleGet<Keys extends readonly OnyxKey[]>(keys: Keys): Promise<{
|
|
79
79
|
[Index in keyof Keys]: OnyxValue<Keys[Index]>;
|
package/dist/OnyxUtils.js
CHANGED
|
@@ -314,7 +314,7 @@ function multiGet(keys) {
|
|
|
314
314
|
* This helper exists to map an array of Onyx keys such as `['report_', 'conciergeReportID']`
|
|
315
315
|
* to the values for those keys (correctly typed) such as `[OnyxCollection<Report>, OnyxEntry<string>]`
|
|
316
316
|
*
|
|
317
|
-
* Note: just using
|
|
317
|
+
* Note: just using `.map`, you'd end up with `Array<OnyxCollection<Report>|OnyxEntry<string>>`, which is not what we want. This preserves the order of the keys provided.
|
|
318
318
|
*/
|
|
319
319
|
function tupleGet(keys) {
|
|
320
320
|
return Promise.all(keys.map((key) => OnyxUtils.get(key)));
|
package/dist/useOnyx.d.ts
CHANGED
|
@@ -22,6 +22,13 @@ type BaseUseOnyxOptions = {
|
|
|
22
22
|
* If set to `true`, the key can be changed dynamically during the component lifecycle.
|
|
23
23
|
*/
|
|
24
24
|
allowDynamicKey?: boolean;
|
|
25
|
+
/**
|
|
26
|
+
* If the component calling this is the one loading the data by calling an action, then you should set this to `true`.
|
|
27
|
+
*
|
|
28
|
+
* If the component calling this does not load the data then you should set it to `false`, which means that if the data
|
|
29
|
+
* 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.
|
|
30
|
+
*/
|
|
31
|
+
canBeMissing?: boolean;
|
|
25
32
|
};
|
|
26
33
|
type UseOnyxInitialValueOption<TInitialValue> = {
|
|
27
34
|
/**
|
package/dist/useOnyx.js
CHANGED
|
@@ -35,6 +35,7 @@ const GlobalSettings = __importStar(require("./GlobalSettings"));
|
|
|
35
35
|
const useLiveRef_1 = __importDefault(require("./useLiveRef"));
|
|
36
36
|
const usePrevious_1 = __importDefault(require("./usePrevious"));
|
|
37
37
|
const metrics_1 = __importDefault(require("./metrics"));
|
|
38
|
+
const Logger = __importStar(require("./Logger"));
|
|
38
39
|
/**
|
|
39
40
|
* Gets the cached value from the Onyx cache. If the key is a collection key, it will return all the values in the collection.
|
|
40
41
|
* It is a fork of `tryGetCachedValue` from `OnyxUtils` caused by different selector logic in `useOnyx`. It should be unified in the future, when `withOnyx` is removed.
|
|
@@ -58,14 +59,6 @@ function tryGetCachedValue(key) {
|
|
|
58
59
|
});
|
|
59
60
|
return values;
|
|
60
61
|
}
|
|
61
|
-
/**
|
|
62
|
-
* Gets the value from cache and maps it with selector. It changes `null` to `undefined` for `useOnyx` compatibility.
|
|
63
|
-
*/
|
|
64
|
-
function getCachedValue(key, selector) {
|
|
65
|
-
const value = tryGetCachedValue(key);
|
|
66
|
-
const selectedValue = selector ? selector(value) : value;
|
|
67
|
-
return selectedValue !== null && selectedValue !== void 0 ? selectedValue : undefined;
|
|
68
|
-
}
|
|
69
62
|
function useOnyx(key, options, dependencies = []) {
|
|
70
63
|
const connectionRef = (0, react_1.useRef)(null);
|
|
71
64
|
const previousKey = (0, usePrevious_1.default)(key);
|
|
@@ -140,7 +133,8 @@ function useOnyx(key, options, dependencies = []) {
|
|
|
140
133
|
}
|
|
141
134
|
}, [key, options === null || options === void 0 ? void 0 : options.canEvict]);
|
|
142
135
|
const getSnapshot = (0, react_1.useCallback)(() => {
|
|
143
|
-
var _a, _b, _c
|
|
136
|
+
var _a, _b, _c;
|
|
137
|
+
let isOnyxValueDefined = true;
|
|
144
138
|
// We return the initial result right away during the first connection if `initWithStoredValues` is set to `false`.
|
|
145
139
|
if (isFirstConnectionRef.current && (options === null || options === void 0 ? void 0 : options.initWithStoredValues) === false) {
|
|
146
140
|
return resultRef.current;
|
|
@@ -149,11 +143,13 @@ function useOnyx(key, options, dependencies = []) {
|
|
|
149
143
|
// so we can return any cached value right away. After the connection is made, we only
|
|
150
144
|
// update `newValueRef` when `Onyx.connect()` callback is fired.
|
|
151
145
|
if (isFirstConnectionRef.current || shouldGetCachedValueRef.current) {
|
|
152
|
-
//
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
146
|
+
// Gets the value from cache and maps it with selector. It changes `null` to `undefined` for `useOnyx` compatibility.
|
|
147
|
+
const value = tryGetCachedValue(key);
|
|
148
|
+
const selectedValue = selectorRef.current ? selectorRef.current(value) : value;
|
|
149
|
+
newValueRef.current = (selectedValue !== null && selectedValue !== void 0 ? selectedValue : undefined);
|
|
150
|
+
// This flag is `false` when the original Onyx value (without selector) is not defined yet.
|
|
151
|
+
// It will be used later to check if we need to log an alert that the value is missing.
|
|
152
|
+
isOnyxValueDefined = value !== null && value !== undefined;
|
|
157
153
|
// We set this flag to `false` again since we don't want to get the newest cached value every time `getSnapshot()` is executed,
|
|
158
154
|
// and only when `Onyx.connect()` callback is fired.
|
|
159
155
|
shouldGetCachedValueRef.current = false;
|
|
@@ -171,7 +167,7 @@ function useOnyx(key, options, dependencies = []) {
|
|
|
171
167
|
// If data is not present in cache and `initialValue` is set during the first connection,
|
|
172
168
|
// we set the new value to `initialValue` and fetch status to `loaded` since we already have some data to return to the consumer.
|
|
173
169
|
if (isFirstConnectionRef.current && !hasCacheForKey && (options === null || options === void 0 ? void 0 : options.initialValue) !== undefined) {
|
|
174
|
-
newValueRef.current =
|
|
170
|
+
newValueRef.current = options.initialValue;
|
|
175
171
|
newFetchStatus = 'loaded';
|
|
176
172
|
}
|
|
177
173
|
// We do a deep equality check if `selector` is defined, since each `tryGetCachedValue()` call will
|
|
@@ -179,12 +175,12 @@ function useOnyx(key, options, dependencies = []) {
|
|
|
179
175
|
// For the other cases we will only deal with object reference checks, so just a shallow equality check is enough.
|
|
180
176
|
let areValuesEqual;
|
|
181
177
|
if (selectorRef.current) {
|
|
182
|
-
areValuesEqual = (0, fast_equals_1.deepEqual)((
|
|
178
|
+
areValuesEqual = (0, fast_equals_1.deepEqual)((_a = previousValueRef.current) !== null && _a !== void 0 ? _a : undefined, newValueRef.current);
|
|
183
179
|
}
|
|
184
180
|
else {
|
|
185
|
-
areValuesEqual = (0, fast_equals_1.shallowEqual)((
|
|
181
|
+
areValuesEqual = (0, fast_equals_1.shallowEqual)((_b = previousValueRef.current) !== null && _b !== void 0 ? _b : undefined, newValueRef.current);
|
|
186
182
|
}
|
|
187
|
-
// We
|
|
183
|
+
// We update the cached value and the result in the following conditions:
|
|
188
184
|
// We will update the cached value and the result in any of the following situations:
|
|
189
185
|
// - The previously cached value is different from the new value.
|
|
190
186
|
// - The previously cached value is `null` (not set from cache yet) and we have cache for this key
|
|
@@ -194,10 +190,16 @@ function useOnyx(key, options, dependencies = []) {
|
|
|
194
190
|
if (shouldUpdateResult) {
|
|
195
191
|
previousValueRef.current = newValueRef.current;
|
|
196
192
|
// If the new value is `null` we default it to `undefined` to ensure the consumer gets a consistent result from the hook.
|
|
197
|
-
|
|
193
|
+
const newStatus = newFetchStatus !== null && newFetchStatus !== void 0 ? newFetchStatus : 'loaded';
|
|
194
|
+
resultRef.current = [(_c = previousValueRef.current) !== null && _c !== void 0 ? _c : undefined, { status: newStatus }];
|
|
195
|
+
// If `canBeMissing` is set to `false` and the Onyx value of that key is not defined,
|
|
196
|
+
// we log an alert so it can be acknowledged by the consumer.
|
|
197
|
+
if ((options === null || options === void 0 ? void 0 : options.canBeMissing) === false && newStatus === 'loaded' && !isOnyxValueDefined) {
|
|
198
|
+
Logger.logAlert(`useOnyx returned no data for key with canBeMissing set to false.`, { key, showAlert: true });
|
|
199
|
+
}
|
|
198
200
|
}
|
|
199
201
|
return resultRef.current;
|
|
200
|
-
}, [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.initialValue, key, selectorRef]);
|
|
202
|
+
}, [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.initialValue, options === null || options === void 0 ? void 0 : options.canBeMissing, key, selectorRef]);
|
|
201
203
|
const subscribe = (0, react_1.useCallback)((onStoreChange) => {
|
|
202
204
|
isConnectingRef.current = true;
|
|
203
205
|
onStoreChangeFnRef.current = onStoreChange;
|