react-native-onyx
Advanced tools
Comparing version
@@ -0,4 +1,6 @@ | ||
type Parameters = string | Record<string, unknown> | Array<Record<string, unknown>> | Error; | ||
type LogData = { | ||
message: string; | ||
level: 'alert' | 'info' | 'hmmm'; | ||
parameters?: Parameters; | ||
}; | ||
@@ -13,11 +15,11 @@ type LoggerCallback = (data: LogData) => void; | ||
*/ | ||
declare function logAlert(message: string): void; | ||
declare function logAlert(message: string, parameters?: Parameters): void; | ||
/** | ||
* Send an info message to the logger | ||
*/ | ||
declare function logInfo(message: string): void; | ||
declare function logInfo(message: string, parameters?: Parameters): void; | ||
/** | ||
* Send an hmmm message to the logger | ||
*/ | ||
declare function logHmmm(message: string): void; | ||
declare function logHmmm(message: string, parameters?: Parameters): void; | ||
export { registerLogger, logInfo, logAlert, logHmmm }; |
@@ -16,4 +16,4 @@ "use strict"; | ||
*/ | ||
function logAlert(message) { | ||
logger({ message: `[Onyx] ${message}`, level: 'alert' }); | ||
function logAlert(message, parameters) { | ||
logger({ message: `[Onyx] ${message}`, level: 'alert', parameters }); | ||
} | ||
@@ -24,4 +24,4 @@ exports.logAlert = logAlert; | ||
*/ | ||
function logInfo(message) { | ||
logger({ message: `[Onyx] ${message}`, level: 'info' }); | ||
function logInfo(message, parameters) { | ||
logger({ message: `[Onyx] ${message}`, level: 'info', parameters }); | ||
} | ||
@@ -32,5 +32,5 @@ exports.logInfo = logInfo; | ||
*/ | ||
function logHmmm(message) { | ||
logger({ message: `[Onyx] ${message}`, level: 'hmmm' }); | ||
function logHmmm(message, parameters) { | ||
logger({ message: `[Onyx] ${message}`, level: 'hmmm', parameters }); | ||
} | ||
exports.logHmmm = logHmmm; |
@@ -76,3 +76,3 @@ import type { ValueOf } from 'type-fest'; | ||
* | ||
* 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. | ||
* 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. | ||
*/ | ||
@@ -79,0 +79,0 @@ declare function tupleGet<Keys extends readonly OnyxKey[]>(keys: Keys): Promise<{ |
@@ -317,3 +317,3 @@ "use strict"; | ||
* | ||
* 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. | ||
* 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. | ||
*/ | ||
@@ -320,0 +320,0 @@ function tupleGet(keys) { |
@@ -25,2 +25,9 @@ import type { DependencyList } from 'react'; | ||
allowDynamicKey?: boolean; | ||
/** | ||
* 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. | ||
*/ | ||
canBeMissing?: boolean; | ||
}; | ||
@@ -27,0 +34,0 @@ type UseOnyxInitialValueOption<TInitialValue> = { |
@@ -38,2 +38,3 @@ "use strict"; | ||
const metrics_1 = __importDefault(require("./metrics")); | ||
const Logger = __importStar(require("./Logger")); | ||
/** | ||
@@ -62,10 +63,2 @@ * Gets the cached value from the Onyx cache. If the key is a collection key, it will return all the values in the collection. | ||
} | ||
/** | ||
* Gets the value from cache and maps it with selector. It changes `null` to `undefined` for `useOnyx` compatibility. | ||
*/ | ||
function getCachedValue(key, selector) { | ||
const value = tryGetCachedValue(key); | ||
const selectedValue = selector ? selector(value) : value; | ||
return selectedValue !== null && selectedValue !== void 0 ? selectedValue : undefined; | ||
} | ||
function useOnyx(key, options, dependencies = []) { | ||
@@ -145,3 +138,4 @@ const connectionRef = (0, react_1.useRef)(null); | ||
const getSnapshot = (0, react_1.useCallback)(() => { | ||
var _a, _b, _c, _d; | ||
var _a, _b, _c; | ||
let isOnyxValueDefined = true; | ||
// We return the initial result right away during the first connection if `initWithStoredValues` is set to `false`. | ||
@@ -155,7 +149,9 @@ if (isFirstConnectionRef.current && (options === null || options === void 0 ? void 0 : options.initWithStoredValues) === false) { | ||
if (isFirstConnectionRef.current || shouldGetCachedValueRef.current) { | ||
// If `newValueRef.current` is `undefined` it means that the cache doesn't have a value for that key yet. | ||
// If `newValueRef.current` is `null` or any other value it means that the cache does have a value for that key. | ||
// This difference between `undefined` and other values is crucial and it's used to address the following | ||
// conditions and use cases. | ||
newValueRef.current = getCachedValue(key, selectorRef.current); | ||
// Gets the value from cache and maps it with selector. It changes `null` to `undefined` for `useOnyx` compatibility. | ||
const value = tryGetCachedValue(key); | ||
const selectedValue = selectorRef.current ? selectorRef.current(value) : value; | ||
newValueRef.current = (selectedValue !== null && selectedValue !== void 0 ? selectedValue : undefined); | ||
// This flag is `false` when the original Onyx value (without selector) is not defined yet. | ||
// It will be used later to check if we need to log an alert that the value is missing. | ||
isOnyxValueDefined = value !== null && value !== undefined; | ||
// We set this flag to `false` again since we don't want to get the newest cached value every time `getSnapshot()` is executed, | ||
@@ -178,3 +174,3 @@ // and only when `Onyx.connect()` callback is fired. | ||
if (isFirstConnectionRef.current && !hasCacheForKey && (options === null || options === void 0 ? void 0 : options.initialValue) !== undefined) { | ||
newValueRef.current = ((_a = options === null || options === void 0 ? void 0 : options.initialValue) !== null && _a !== void 0 ? _a : undefined); | ||
newValueRef.current = options.initialValue; | ||
newFetchStatus = 'loaded'; | ||
@@ -187,8 +183,8 @@ } | ||
if (selectorRef.current) { | ||
areValuesEqual = (0, fast_equals_1.deepEqual)((_b = previousValueRef.current) !== null && _b !== void 0 ? _b : undefined, newValueRef.current); | ||
areValuesEqual = (0, fast_equals_1.deepEqual)((_a = previousValueRef.current) !== null && _a !== void 0 ? _a : undefined, newValueRef.current); | ||
} | ||
else { | ||
areValuesEqual = (0, fast_equals_1.shallowEqual)((_c = previousValueRef.current) !== null && _c !== void 0 ? _c : undefined, newValueRef.current); | ||
areValuesEqual = (0, fast_equals_1.shallowEqual)((_b = previousValueRef.current) !== null && _b !== void 0 ? _b : undefined, newValueRef.current); | ||
} | ||
// We updated the cached value and the result in the following conditions: | ||
// We update the cached value and the result in the following conditions: | ||
// We will update the cached value and the result in any of the following situations: | ||
@@ -203,6 +199,12 @@ // - The previously cached value is different from the new value. | ||
// If the new value is `null` we default it to `undefined` to ensure the consumer gets a consistent result from the hook. | ||
resultRef.current = [(_d = previousValueRef.current) !== null && _d !== void 0 ? _d : undefined, { status: newFetchStatus !== null && newFetchStatus !== void 0 ? newFetchStatus : 'loaded' }]; | ||
const newStatus = newFetchStatus !== null && newFetchStatus !== void 0 ? newFetchStatus : 'loaded'; | ||
resultRef.current = [(_c = previousValueRef.current) !== null && _c !== void 0 ? _c : undefined, { status: newStatus }]; | ||
// If `canBeMissing` is set to `false` and the Onyx value of that key is not defined, | ||
// we log an alert so it can be acknowledged by the consumer. | ||
if ((options === null || options === void 0 ? void 0 : options.canBeMissing) === false && newStatus === 'loaded' && !isOnyxValueDefined) { | ||
Logger.logAlert(`useOnyx returned no data for key with canBeMissing set to false.`, { key, showAlert: true }); | ||
} | ||
} | ||
return resultRef.current; | ||
}, [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]); | ||
}, [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]); | ||
const subscribe = (0, react_1.useCallback)((onStoreChange) => { | ||
@@ -209,0 +211,0 @@ isConnectingRef.current = true; |
{ | ||
"name": "react-native-onyx", | ||
"version": "2.0.94", | ||
"version": "2.0.95", | ||
"author": "Expensify, Inc.", | ||
@@ -5,0 +5,0 @@ "homepage": "https://expensify.com", |
@@ -259,2 +259,17 @@ # `react-native-onyx` | ||
### useOnyx()'s `canBeMissing` option | ||
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. | ||
```javascript | ||
const Component = ({reportID}) => { | ||
// This hook will log an alert (via `Logger.logAlert()`) if `report` is `undefined`. | ||
const [report] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${reportID}`, {canBeMissing: false}); | ||
// rest of the component's code. | ||
}; | ||
export default Component; | ||
``` | ||
## Collections | ||
@@ -261,0 +276,0 @@ |
332302
0.59%6062
0.2%527
2.93%