diff --git a/API-INTERNAL.md b/API-INTERNAL.md index a31fa6135..34ec4bf37 100644 --- a/API-INTERNAL.md +++ b/API-INTERNAL.md @@ -20,9 +20,15 @@
getSkippableCollectionMemberIDs()

Getter - returns the skippable collection member IDs.

+
getSnapshotMergeKeys()
+

Getter - returns the snapshot merge keys allowlist.

+
setSkippableCollectionMemberIDs()

Setter - sets the skippable collection member IDs.

+
setSnapshotMergeKeys()
+

Setter - sets the snapshot merge keys allowlist.

+
initStoreValues(keys, initialKeyStates, evictableKeys)

Sets the initial values for the Onyx store

@@ -222,12 +228,24 @@ Getter - returns the deffered init task. ## getSkippableCollectionMemberIDs() Getter - returns the skippable collection member IDs. +**Kind**: global function + + +## getSnapshotMergeKeys() +Getter - returns the snapshot merge keys allowlist. + **Kind**: global function ## setSkippableCollectionMemberIDs() Setter - sets the skippable collection member IDs. +**Kind**: global function + + +## setSnapshotMergeKeys() +Setter - sets the snapshot merge keys allowlist. + **Kind**: global function diff --git a/README.md b/README.md index e5384e8dc..dd32a0e66 100644 --- a/README.md +++ b/README.md @@ -206,21 +206,6 @@ export default App; 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). -### 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 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`). diff --git a/lib/OnyxSnapshotCache.ts b/lib/OnyxSnapshotCache.ts index 0d6871c96..b277163b4 100644 --- a/lib/OnyxSnapshotCache.ts +++ b/lib/OnyxSnapshotCache.ts @@ -60,19 +60,17 @@ class OnyxSnapshotCache { * - `selector`: Different selectors produce different results, so each selector needs its own cache entry * - `initWithStoredValues`: This flag changes the initial loading behavior and affects the returned fetch status * - `allowStaleData`: Controls whether stale data can be returned during pending merges, affecting result timing - * - `canBeMissing`: Determines logging behavior for missing data, but doesn't affect the actual data returned * * Other options like `canEvict`, `reuseConnection`, and `allowDynamicKey` don't affect the data transformation * or timing behavior of getSnapshot, so they're excluded from the cache key for better cache hit rates. */ - registerConsumer(options: Pick, 'selector' | 'initWithStoredValues' | 'allowStaleData' | 'canBeMissing'>): string { + registerConsumer(options: Pick, 'selector' | 'initWithStoredValues' | 'allowStaleData'>): string { const selectorID = options?.selector ? this.getSelectorID(options.selector) : 'no_selector'; // Create options hash without expensive JSON.stringify const initWithStoredValues = options?.initWithStoredValues ?? true; const allowStaleData = options?.allowStaleData ?? false; - const canBeMissing = options?.canBeMissing ?? true; - const cacheKey = `${selectorID}_${initWithStoredValues}_${allowStaleData}_${canBeMissing}`; + const cacheKey = `${selectorID}_${initWithStoredValues}_${allowStaleData}`; // Increment reference count for this cache key const currentCount = this.cacheKeyRefCounts.get(cacheKey) || 0; diff --git a/lib/useOnyx.ts b/lib/useOnyx.ts index 0b28a450b..8428e27d3 100644 --- a/lib/useOnyx.ts +++ b/lib/useOnyx.ts @@ -9,7 +9,6 @@ import * as GlobalSettings from './GlobalSettings'; import type {CollectionKeyBase, OnyxKey, OnyxValue} from './types'; import usePrevious from './usePrevious'; import decorateWithMetrics from './metrics'; -import * as Logger from './Logger'; import onyxSnapshotCache from './OnyxSnapshotCache'; import useLiveRef from './useLiveRef'; @@ -43,14 +42,6 @@ type UseOnyxOptions = { */ 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; - /** * This will be used to subscribe to a subset of an Onyx key's data. * Using this setting on `useOnyx` can have very positive performance benefits because the component will only re-render @@ -156,9 +147,8 @@ function useOnyx>( selector: options?.selector, initWithStoredValues: options?.initWithStoredValues, allowStaleData: options?.allowStaleData, - canBeMissing: options?.canBeMissing, }), - [options?.selector, options?.initWithStoredValues, options?.allowStaleData, options?.canBeMissing], + [options?.selector, options?.initWithStoredValues, options?.allowStaleData], ); useEffect(() => () => onyxSnapshotCache.deregisterConsumer(key, cacheKey), [key, cacheKey]); @@ -242,8 +232,6 @@ function useOnyx>( } } - let isOnyxValueDefined = true; - // We return the initial result right away during the first connection if `initWithStoredValues` is set to `false`. if (isFirstConnectionRef.current && options?.initWithStoredValues === false) { const result = resultRef.current; @@ -262,10 +250,6 @@ function useOnyx>( const selectedValue = memoizedSelector ? memoizedSelector(value) : value; newValueRef.current = (selectedValue ?? undefined) as TReturnValue | 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, // and only when `Onyx.connect()` callback is fired. shouldGetCachedValueRef.current = false; @@ -317,13 +301,6 @@ function useOnyx>( sourceValue: sourceValueRef.current, }, ]; - - // 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. Additionally, we won't log alerts - // if there's a `Onyx.clear()` task in progress. - if (options?.canBeMissing === false && newFetchStatus === 'loaded' && !isOnyxValueDefined && !OnyxCache.hasPendingTask(TASK.CLEAR)) { - Logger.logAlert(`useOnyx returned no data for key with canBeMissing set to false for key ${key}`, {showAlert: true}); - } } if (newFetchStatus !== 'loading') { @@ -331,7 +308,7 @@ function useOnyx>( } return resultRef.current; - }, [options?.initWithStoredValues, options?.allowStaleData, options?.canBeMissing, key, memoizedSelector, cacheKey, previousKey]); + }, [options?.initWithStoredValues, options?.allowStaleData, key, memoizedSelector, cacheKey, previousKey]); const subscribe = useCallback( (onStoreChange: () => void) => { diff --git a/package-lock.json b/package-lock.json index 0b86abad8..d333c70fa 100644 --- a/package-lock.json +++ b/package-lock.json @@ -211,6 +211,7 @@ "integrity": "sha512-fcdRcWahONYo+JRnJg1/AekOacGvKx12Gu0qXJXFi2WBqQA1i7+O5PaxRB7kxE/Op94dExnCiiar6T09pvdHpA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@nicolo-ribaudo/eslint-scope-5-internals": "5.1.1-v1", "eslint-visitor-keys": "^2.1.0", @@ -538,7 +539,6 @@ "integrity": "sha512-87GDMS3tsmMSi/3bWOte1UblL+YUTFMV8SZPZ2eSEL17s74Cw/l63rR6NmGVKMYW2GYi85nE+/d6Hw5N0bEk2Q==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.27.1", "@babel/traverse": "^7.28.5" @@ -556,7 +556,6 @@ "integrity": "sha512-qNeq3bCKnGgLkEXUuFry6dPlGfCdQNZbn7yUAPCInwAJHMU7THJfrBSozkcWq5sNM6RcF3S8XyQL2A52KNR9IA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, @@ -573,7 +572,6 @@ "integrity": "sha512-g4L7OYun04N1WyqMNjldFwlfPCLVkgB54A/YCXICZYBsvJJE3kByKv9c9+R/nAfmIfjl2rKYLNyMHboYbZaWaA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, @@ -590,7 +588,6 @@ "integrity": "sha512-oO02gcONcD5O1iTLi/6frMJBIwWEHceWGSGqrpCmEL8nogiS6J9PBlE48CaK20/Jx1LuRml9aDftLgdjXT8+Cw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.27.1", "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1", @@ -609,7 +606,6 @@ "integrity": "sha512-b6YTX108evsvE4YgWyQ921ZAFFQm3Bn+CA3+ZXlNVnPhx+UfsVURoPjfGAPCjBgrqo30yX/C2nZGX96DxvR9Iw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.27.1", "@babel/traverse": "^7.28.3" @@ -698,7 +694,6 @@ "integrity": "sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=6.9.0" }, @@ -812,7 +807,6 @@ "integrity": "sha512-UT/Jrhw57xg4ILHLFnzFpPDlMbcdEicaAtjPQpbj9wa8T4r5KVWCimHcL/460g8Ht0DMxDyjsLgiWSkVjnwPFg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, @@ -1013,7 +1007,6 @@ "integrity": "sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.18.6", "@babel/helper-plugin-utils": "^7.18.6" @@ -1083,7 +1076,6 @@ "integrity": "sha512-cnqkuOtZLapWYZUYM5rVIdv1nXYuFVIltZ6ZJ7nIj585QsjKM5dhL2Fu/lICXZ1OyIAFc7Qy+bvDAtTXqGrlhg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, @@ -1133,7 +1125,6 @@ "integrity": "sha512-LtPXlBbRoc4Njl/oh1CeD/3jC+atytbnf/UqLoqTDcEYGUPj022+rvfkbDYieUrSj3CaV4yHDByPE+T2HwfsJg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-create-class-features-plugin": "^7.28.3", "@babel/helper-plugin-utils": "^7.27.1" @@ -1206,7 +1197,6 @@ "integrity": "sha512-gEbkDVGRvjj7+T1ivxrfgygpT7GUd4vmODtYpbs0gZATdkX8/iSnOtZSxiZnsgm1YjTgjI6VKBGSJJevkrclzw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.27.1", "@babel/helper-plugin-utils": "^7.27.1" @@ -1224,7 +1214,6 @@ "integrity": "sha512-MTyJk98sHvSs+cvZ4nOauwTTG1JeonDjSGvGGUNHreGQns+Mpt6WX/dVzWBHgg+dYZhkC4X+zTDfkTU+Vy9y7Q==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, @@ -1241,7 +1230,6 @@ "integrity": "sha512-hkGcueTEzuhB30B3eJCbCYeCaaEQOmQR0AdvzpD4LoN0GXMWzzGSuRrxR2xTnCrvNbVwK9N6/jQ92GSLfiZWoQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.27.1", "@babel/helper-plugin-utils": "^7.27.1" @@ -1259,7 +1247,6 @@ "integrity": "sha512-MHzkWQcEmjzzVW9j2q8LGjwGWpG2mjwaaB0BNQwst3FIjqsg8Ct/mIZlvSPJvfi9y2AC8mi/ktxbFVL9pZ1I4A==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, @@ -1276,7 +1263,6 @@ "integrity": "sha512-K8nhUcn3f6iB+P3gwCv/no7OdzOZQcKchW6N389V6PD8NUWKZHzndOd9sPDVbMoBsbmjMqlB4L9fm+fEFNVlwQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.27.1", "@babel/plugin-transform-destructuring": "^7.28.0" @@ -1294,7 +1280,6 @@ "integrity": "sha512-D4WIMaFtwa2NizOp+dnoFjRez/ClKiC2BqqImwKd1X28nqBtZEyCYJ2ozQrrzlxAFrcrjxo39S6khe9RNDlGzw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, @@ -1311,7 +1296,6 @@ "integrity": "sha512-tQvHWSZ3/jH2xuq/vZDy0jNn+ZdXJeM8gHvX4lnJmsc3+50yPlWdZXIc5ay+umX+2/tJIqHqiEqcJvxlmIvRvQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, @@ -1380,7 +1364,6 @@ "integrity": "sha512-6WVLVJiTjqcQauBhn1LkICsR2H+zm62I3h9faTDKt1qP4jn2o72tSvqMwtGFKGTpojce0gJs+76eZ2uCHRZh0Q==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, @@ -1429,7 +1412,6 @@ "integrity": "sha512-hqoBX4dcZ1I33jCSWcXrP+1Ku7kdqXf1oeah7ooKOIiAdKQ+uqftgCFNOSzA5AMS2XIHEYeGFg4cKRCdpxzVOQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, @@ -1446,7 +1428,6 @@ "integrity": "sha512-iCsytMg/N9/oFq6n+gFTvUYDZQOMK5kEdeYxmxt91fcJGycfxVP9CnrxoliM0oumFERba2i8ZtwRUCMhvP1LnA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-module-transforms": "^7.27.1", "@babel/helper-plugin-utils": "^7.27.1" @@ -1481,7 +1462,6 @@ "integrity": "sha512-vn5Jma98LCOeBy/KpeQhXcV2WZgaRUtjwQmjoBuLNlOmkg0fB5pdvYVeWRYI69wWKwK2cD1QbMiUQnoujWvrew==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-module-transforms": "^7.28.3", "@babel/helper-plugin-utils": "^7.27.1", @@ -1501,7 +1481,6 @@ "integrity": "sha512-iQBE/xC5BV1OxJbp6WG7jq9IWiD+xxlZhLrdwpPkTX3ydmXdvoCpyfJN7acaIBZaOqTfr76pgzqBJflNbeRK+w==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-module-transforms": "^7.27.1", "@babel/helper-plugin-utils": "^7.27.1" @@ -1536,7 +1515,6 @@ "integrity": "sha512-f6PiYeqXQ05lYq3TIfIDu/MtliKUbNwkGApPUvyo6+tc7uaR4cPjPe7DFPr15Uyycg2lZU6btZ575CuQoYh7MQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, @@ -1605,7 +1583,6 @@ "integrity": "sha512-SFy8S9plRPbIcxlJ8A6mT/CxFdJx/c04JEctz4jf8YZaVS2px34j7NXRrlGlHkN/M2gnpL37ZpGRGVFLd3l8Ng==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.27.1", "@babel/helper-replace-supers": "^7.27.1" @@ -1707,7 +1684,6 @@ "integrity": "sha512-oThy3BCuCha8kDZ8ZkgOg2exvPYUlprMukKQXI1r1pJ47NCvxfkEy8vK+r/hT9nF0Aa4H1WUPZZjHTFtAhGfmQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, @@ -1808,7 +1784,6 @@ "integrity": "sha512-TtEciroaiODtXvLZv4rmfMhkCv8jx3wgKpL68PuiPh2M4fvz5jhsA7697N1gMvkvr/JTF13DrFYyEbY9U7cVPA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.27.1", "@babel/helper-plugin-utils": "^7.27.1" @@ -1826,7 +1801,6 @@ "integrity": "sha512-V2ABPHIJX4kC7HegLkYoDpfg9PVmuWy/i6vUM5eGK22bx4YVFD3M5F0QQnWQoDs6AGsUWTVOopBiMFQgHaSkVw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, @@ -1913,7 +1887,6 @@ "integrity": "sha512-fBJKiV7F2DxZUkg5EtHKXQdbsbURW3DZKQUWphDum0uRP6eHGGa/He9mc0mypL680pb+e/lDIthRohlv8NCHkg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, @@ -1930,7 +1903,6 @@ "integrity": "sha512-RiSILC+nRJM7FY5srIyc4/fGIwUhyDuuBSdWn4y6yT6gm652DpCHZjIipgn6B7MQ1ITOUnAKWixEUjQRIBIcLw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, @@ -1967,7 +1939,6 @@ "integrity": "sha512-Ysg4v6AmF26k9vpfFuTZg8HRfVWzsh1kVfowA23y9j/Gu6dOuahdUVhkLqpObp3JIv27MLSii6noRnuKN8H0Mg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, @@ -1984,7 +1955,6 @@ "integrity": "sha512-uW20S39PnaTImxp39O5qFlHLS9LJEmANjMG7SxIhap8rCHqu0Ik+tLEPX5DKmHn6CsWQ7j3lix2tFOa5YtL12Q==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.27.1", "@babel/helper-plugin-utils": "^7.27.1" @@ -2019,7 +1989,6 @@ "integrity": "sha512-EtkOujbc4cgvb0mlpQefi4NTPBzhSIevblFevACNLUspmrALgmEBdL/XfnyyITfd8fKBZrZys92zOWcik7j9Tw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.27.1", "@babel/helper-plugin-utils": "^7.27.1" @@ -2141,7 +2110,6 @@ "integrity": "sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.0.0", "@babel/types": "^7.4.4", @@ -3457,6 +3425,7 @@ "integrity": "sha512-TiZzBSJja/LbhNPvk6yc0JrX9XqhQ0hdh6M2svYfsHGejaKFIAGd9MQ+ERIMzLGlN/kZoYIgdxFV0PuljTKXag==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@eslint-community/regexpp": "^4.4.0", "@typescript-eslint/scope-manager": "5.62.0", @@ -3492,6 +3461,7 @@ "integrity": "sha512-VlJEV0fOQ7BExOsHYAGrgbEiZoi8D+Bl2+f6V2RrXerRSylnp+ZBHmPvaIa8cz0Ajx7WO7Z5RqfgYg7ED1nRhA==", "dev": true, "license": "BSD-2-Clause", + "peer": true, "dependencies": { "@typescript-eslint/scope-manager": "5.62.0", "@typescript-eslint/types": "5.62.0", @@ -4251,6 +4221,7 @@ "integrity": "sha512-promo4eFwuiW+TfGxhi+0x3czqTYJkG8qB17ZUJiVF10Xm7NLVRSLUsfRTU/6h1e24VvRnXCx+hG7li58lkzog==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@types/linkify-it": "^5", "@types/mdurl": "^2" @@ -4269,6 +4240,7 @@ "integrity": "sha512-OP+We5WV8Xnbuvw0zC2m4qfB/BJvjyCwtNjhHdJxV1639SGSKrLmJkc3fMnp2Qy8nJyHp8RO6umxELN/dS1/EA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "undici-types": "~6.21.0" } @@ -4401,6 +4373,7 @@ "integrity": "sha512-3xP4XzzDNQOIqBMWogftkwxhg5oMKApqY0BAflmLZiFYHqyhSOxv/cd/zPQLTcCXr4AkaKb25joocY0BD1WC6A==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@typescript-eslint/scope-manager": "8.51.0", "@typescript-eslint/types": "8.51.0", @@ -4932,6 +4905,7 @@ "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", "dev": true, "license": "MIT", + "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -5735,6 +5709,7 @@ } ], "license": "MIT", + "peer": true, "dependencies": { "caniuse-lite": "^1.0.30001726", "electron-to-chromium": "^1.5.173", @@ -7351,6 +7326,7 @@ "integrity": "sha512-LEyamqS7W5HB3ujJyvi0HQK/dtVINZvd5mAAp9eT5S/ujByGjiZLCzPcHVzuXbpJDJF/cxwHlfceVUDZ2lnSTw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/regexpp": "^4.12.1", @@ -10343,6 +10319,7 @@ "integrity": "sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@jest/core": "^29.7.0", "@jest/types": "^29.6.3", @@ -11623,6 +11600,7 @@ "integrity": "sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "argparse": "^2.0.1", "entities": "^4.4.0", @@ -13081,6 +13059,7 @@ "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">=12" }, @@ -13213,6 +13192,7 @@ "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==", "dev": true, "license": "MIT", + "peer": true, "bin": { "prettier": "bin-prettier.js" }, @@ -13418,6 +13398,7 @@ "integrity": "sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "loose-envify": "^1.1.0" }, @@ -13471,6 +13452,7 @@ "integrity": "sha512-0TUhgmlouRNf6yuDIIAdbQl0g1VsONgCMsLs7Et64hjj5VLMCA7np+4dMrZvGZ3wRNqzgeyT9oWJsUm49AcwSQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@jest/create-cache-key-function": "^29.6.3", "@react-native/assets-registry": "0.76.3", @@ -13544,6 +13526,7 @@ "dev": true, "hasInstallScript": true, "license": "MIT", + "peer": true, "peerDependencies": { "react": "*", "react-native": "*" @@ -13671,6 +13654,7 @@ "integrity": "sha512-JWD+aQ0lh2gvh4NM3bBM42Kx+XybOxCpgYK7F8ugAlpaTSnWsX+39Z4XkOykGZAHrjwwTZT3x3KxswVWxHPUqA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "react-is": "^18.2.0", "react-shallow-renderer": "^16.15.0", @@ -15472,6 +15456,7 @@ "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@cspotcode/source-map-support": "^0.8.0", "@tsconfig/node10": "^1.0.7", @@ -15884,6 +15869,7 @@ "integrity": "sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A==", "dev": true, "license": "Apache-2.0", + "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -16043,6 +16029,7 @@ "dev": true, "hasInstallScript": true, "license": "MIT", + "peer": true, "dependencies": { "napi-postinstall": "^0.3.0" }, diff --git a/tests/perf-test/OnyxSnapshotCache.perf-test.ts b/tests/perf-test/OnyxSnapshotCache.perf-test.ts index 7c1e5ed8e..a160d6eb9 100644 --- a/tests/perf-test/OnyxSnapshotCache.perf-test.ts +++ b/tests/perf-test/OnyxSnapshotCache.perf-test.ts @@ -39,14 +39,12 @@ const selectorOptions: UseOnyxOptions = { selector: simpleSelector, initWithStoredValues: true, allowStaleData: false, - canBeMissing: true, }; const complexSelectorOptions: UseOnyxOptions = { selector: complexSelector, initWithStoredValues: true, allowStaleData: false, - canBeMissing: true, }; // Mock results diff --git a/tests/unit/OnyxSnapshotCacheTest.ts b/tests/unit/OnyxSnapshotCacheTest.ts index daaf5fcd4..de1ce2d89 100644 --- a/tests/unit/OnyxSnapshotCacheTest.ts +++ b/tests/unit/OnyxSnapshotCacheTest.ts @@ -40,12 +40,10 @@ describe('OnyxSnapshotCache', () => { selector, initWithStoredValues: true, allowStaleData: false, - canBeMissing: true, }; const optionsWithoutSelector: UseOnyxOptions = { initWithStoredValues: false, allowStaleData: true, - canBeMissing: false, }; const keyWithSelector = cache.registerConsumer(optionsWithSelector); const keyWithoutSelector = cache.registerConsumer(optionsWithoutSelector); diff --git a/tests/unit/useOnyxTest.ts b/tests/unit/useOnyxTest.ts index 19fe2cd09..80176e58c 100644 --- a/tests/unit/useOnyxTest.ts +++ b/tests/unit/useOnyxTest.ts @@ -5,7 +5,6 @@ import OnyxCache from '../../lib/OnyxCache'; import StorageMock from '../../lib/storage'; import type GenericCollection from '../utils/GenericCollection'; import waitForPromisesToResolve from '../utils/waitForPromisesToResolve'; -import * as Logger from '../../lib/Logger'; import onyxSnapshotCache from '../../lib/OnyxSnapshotCache'; import type {UseOnyxSelector} from '../../lib/useOnyx'; @@ -1019,158 +1018,6 @@ describe('useOnyx', () => { }); }); - describe('canBeMissing', () => { - let logAlertFn = jest.fn(); - const alertMessage = 'useOnyx returned no data for key with canBeMissing set to false for key test'; - - beforeEach(() => { - logAlertFn = jest.fn(); - jest.spyOn(Logger, 'logAlert').mockImplementation(logAlertFn); - }); - - afterEach(() => { - (Logger.logAlert as unknown as jest.SpyInstance>).mockRestore(); - }); - - it('should not log an alert if Onyx doesn\'t return data in loaded state and "canBeMissing" property is not provided', async () => { - const {result: result1} = renderHook(() => useOnyx(ONYXKEYS.TEST_KEY)); - - expect(result1.current[0]).toBeUndefined(); - expect(result1.current[1].status).toEqual('loading'); - - await act(async () => waitForPromisesToResolve()); - - expect(result1.current[0]).toBeUndefined(); - expect(result1.current[1].status).toEqual('loaded'); - expect(logAlertFn).not.toBeCalled(); - - await act(async () => Onyx.set(ONYXKEYS.TEST_KEY, 'test')); - - expect(result1.current[0]).toBe('test'); - - await act(async () => Onyx.set(ONYXKEYS.TEST_KEY, null)); - - expect(result1.current[0]).toBeUndefined(); - expect(logAlertFn).not.toBeCalled(); - }); - - it('should not log an alert if Onyx doesn\'t return data, "canBeMissing" property is false but "initWithStoredValues" is also false', async () => { - const {result: result1} = renderHook(() => useOnyx(ONYXKEYS.TEST_KEY, {canBeMissing: false, initWithStoredValues: false})); - - expect(result1.current[0]).toBeUndefined(); - expect(result1.current[1].status).toEqual('loaded'); - - expect(logAlertFn).not.toBeCalled(); - }); - - it('should log an alert if Onyx doesn\'t return data in loaded state and "canBeMissing" property is false', async () => { - const {result: result1} = renderHook(() => useOnyx(ONYXKEYS.TEST_KEY, {canBeMissing: false})); - - expect(result1.current[0]).toBeUndefined(); - expect(result1.current[1].status).toEqual('loading'); - expect(logAlertFn).not.toBeCalled(); - - await act(async () => waitForPromisesToResolve()); - - expect(result1.current[0]).toBeUndefined(); - expect(result1.current[1].status).toEqual('loaded'); - expect(logAlertFn).toHaveBeenCalledTimes(1); - expect(logAlertFn).toHaveBeenNthCalledWith(1, alertMessage, {showAlert: true}); - - await act(async () => Onyx.set(ONYXKEYS.TEST_KEY, 'test')); - - expect(result1.current[0]).toBe('test'); - - await act(async () => Onyx.set(ONYXKEYS.TEST_KEY, null)); - - expect(result1.current[0]).toBeUndefined(); - expect(logAlertFn).toHaveBeenCalledTimes(2); - expect(logAlertFn).toHaveBeenNthCalledWith(2, alertMessage, {showAlert: true}); - }); - - it('should log an alert if Onyx doesn\'t return selected data in loaded state and "canBeMissing" property is false', async () => { - const {result: result1} = renderHook(() => - useOnyx(ONYXKEYS.TEST_KEY, { - selector: ((entry: OnyxEntry) => (entry ? `${entry}_changed` : undefined)) as UseOnyxSelector, - canBeMissing: false, - }), - ); - - expect(result1.current[0]).toBeUndefined(); - expect(result1.current[1].status).toEqual('loading'); - expect(logAlertFn).not.toBeCalled(); - - await act(async () => waitForPromisesToResolve()); - - expect(result1.current[0]).toBeUndefined(); - expect(result1.current[1].status).toEqual('loaded'); - expect(logAlertFn).toHaveBeenCalledTimes(1); - expect(logAlertFn).toHaveBeenNthCalledWith(1, alertMessage, {showAlert: true}); - - await act(async () => Onyx.set(ONYXKEYS.TEST_KEY, 'test')); - - expect(result1.current[0]).toBe('test_changed'); - - await act(async () => Onyx.set(ONYXKEYS.TEST_KEY, null)); - - expect(result1.current[0]).toBeUndefined(); - expect(logAlertFn).toHaveBeenCalledTimes(2); - expect(logAlertFn).toHaveBeenNthCalledWith(2, alertMessage, {showAlert: true}); - }); - - it('should log an alert if Onyx doesn\'t return data but there is a selector that always return something and "canBeMissing" property is false', async () => { - const {result: result1} = renderHook(() => - useOnyx(ONYXKEYS.TEST_KEY, { - // This selector will always return a value, even if the Onyx data is missing. - selector: ((entry: OnyxEntry) => `${entry}_changed`) as UseOnyxSelector, - canBeMissing: false, - }), - ); - - await act(async () => waitForPromisesToResolve()); - - expect(result1.current[0]).toBe('undefined_changed'); - expect(result1.current[1].status).toEqual('loaded'); - expect(logAlertFn).toHaveBeenCalledTimes(1); - expect(logAlertFn).toHaveBeenNthCalledWith(1, alertMessage, {showAlert: true}); - - await act(async () => Onyx.set(ONYXKEYS.TEST_KEY, 'test')); - - expect(result1.current[0]).toBe('test_changed'); - - await act(async () => Onyx.set(ONYXKEYS.TEST_KEY, null)); - - expect(result1.current[0]).toBe('undefined_changed'); - expect(logAlertFn).toHaveBeenCalledTimes(2); - expect(logAlertFn).toHaveBeenNthCalledWith(2, alertMessage, {showAlert: true}); - }); - - it('should not log an alert if "canBeMissing" property is false but there is a Onyx.clear() task in progress', async () => { - const {result: result1} = renderHook(() => useOnyx(ONYXKEYS.TEST_KEY, {canBeMissing: false})); - - expect(result1.current[0]).toBeUndefined(); - expect(result1.current[1].status).toEqual('loading'); - expect(logAlertFn).not.toBeCalled(); - - await act(async () => waitForPromisesToResolve()); - - expect(result1.current[0]).toBeUndefined(); - expect(result1.current[1].status).toEqual('loaded'); - expect(logAlertFn).toHaveBeenCalledTimes(1); - expect(logAlertFn).toHaveBeenNthCalledWith(1, alertMessage, {showAlert: true}); - - await act(async () => Onyx.set(ONYXKEYS.TEST_KEY, 'test')); - - expect(result1.current[0]).toBe('test'); - - logAlertFn.mockReset(); - await act(async () => Onyx.clear()); - - expect(result1.current[0]).toBeUndefined(); - expect(logAlertFn).not.toBeCalled(); - }); - }); - // This test suite must be the last one to avoid problems when running the other tests here. describe('canEvict', () => { const error = (key: string) => `canEvict can't be used on key '${key}'. This key must explicitly be flagged as safe for removal by adding it to Onyx.init({evictableKeys: []}).`;