From aeb945763d15472778b97f39f23fa0ee66805615 Mon Sep 17 00:00:00 2001
From: Julian Kobrynski
Date: Mon, 26 Jan 2026 15:24:28 +0100
Subject: [PATCH 01/29] add RAM-only key support, store in cache
---
lib/OnyxCache.ts | 19 +++++++++++++++++++
lib/OnyxUtils.ts | 16 ++++++++++++++++
lib/useOnyx.ts | 1 +
3 files changed, 36 insertions(+)
diff --git a/lib/OnyxCache.ts b/lib/OnyxCache.ts
index bceada3b..e40dccbe 100644
--- a/lib/OnyxCache.ts
+++ b/lib/OnyxCache.ts
@@ -55,6 +55,9 @@ class OnyxCache {
/** Set of collection keys for fast lookup */
private collectionKeys = new Set();
+ /** Set of RAM-only keys for fast lookup */
+ private ramOnlyKeys = new Set();
+
constructor() {
this.storageKeys = new Set();
this.nullishStorageKeys = new Set();
@@ -94,6 +97,8 @@ class OnyxCache {
'isCollectionKey',
'getCollectionKey',
'getCollectionData',
+ 'setRamOnlyKeys',
+ 'isRamOnlyKey'
);
}
@@ -474,6 +479,20 @@ class OnyxCache {
// Return a shallow copy to ensure React detects changes when items are added/removed
return {...cachedCollection};
}
+
+ /**
+ * Set the RAM-only keys for optimized storage
+ */
+ setRamOnlyKeys(ramOnlyKeys: Set): void {
+ this.ramOnlyKeys = ramOnlyKeys;
+ }
+
+ /**
+ * Check if a key is a RAM-only key
+ */
+ isRamOnlyKey(key: OnyxKey): boolean {
+ return this.ramOnlyKeys.has(key);
+ }
}
const instance = new OnyxCache();
diff --git a/lib/OnyxUtils.ts b/lib/OnyxUtils.ts
index 88939742..83eea9c1 100644
--- a/lib/OnyxUtils.ts
+++ b/lib/OnyxUtils.ts
@@ -84,6 +84,9 @@ let callbackToStateMapping: Record> = {}
// Keeps a copy of the values of the onyx collection keys as a map for faster lookups
let onyxCollectionKeySet = new Set();
+// Keeps a copy of the values of the onyx RAM-only keys as a map for faster lookups
+let onyxRamOnlyKeySet = new Set();
+
// Holds a mapping of the connected key to the subscriptionID for faster lookups
let onyxKeyToSubscriptionIDs = new Map();
@@ -166,6 +169,12 @@ function initStoreValues(keys: DeepRecord, initialKeyStates: Pa
return acc;
}, new Set());
+ const ramOnlyValues = Object.values(keys.RAM_ONLY ?? {}) as string[];
+ onyxRamOnlyKeySet = ramOnlyValues.reduce((acc, val) => {
+ acc.add(val);
+ return acc;
+ }, new Set());
+
// Set our default key states to use when initializing and clearing Onyx data
defaultKeyStates = initialKeyStates;
@@ -177,6 +186,9 @@ function initStoreValues(keys: DeepRecord, initialKeyStates: Pa
// Set collection keys in cache for optimized storage
cache.setCollectionKeys(onyxCollectionKeySet);
+ // Set RAM-only keys in cache for optimized storage
+ cache.setRamOnlyKeys(onyxRamOnlyKeySet);
+
if (typeof keys.COLLECTION === 'object' && typeof keys.COLLECTION.SNAPSHOT === 'string') {
snapshotKey = keys.COLLECTION.SNAPSHOT;
}
@@ -1321,6 +1333,10 @@ function setWithRetry({key, value, options}: SetParams OnyxUtils.retryOperation(error, setWithRetry, {key, value: valueWithoutNestedNullValues, options}, retryAttempt))
.then(() => {
diff --git a/lib/useOnyx.ts b/lib/useOnyx.ts
index b60214d6..77d7257b 100644
--- a/lib/useOnyx.ts
+++ b/lib/useOnyx.ts
@@ -23,6 +23,7 @@ type UseOnyxOptions = {
/**
* If set to `false`, then no data will be prefilled into the component.
+ * @deprecated This param is going to be removed soon. Use RAM-only keys instead.
*/
initWithStoredValues?: boolean;
From d89ec4f433c5a7627792f65f4d9bbd5829796d29 Mon Sep 17 00:00:00 2001
From: Julian Kobrynski
Date: Tue, 27 Jan 2026 10:36:51 +0100
Subject: [PATCH 02/29] add RAM-only support to multiSetWithRetry method
---
lib/OnyxUtils.ts | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/lib/OnyxUtils.ts b/lib/OnyxUtils.ts
index 83eea9c1..42c32ac4 100644
--- a/lib/OnyxUtils.ts
+++ b/lib/OnyxUtils.ts
@@ -1387,7 +1387,10 @@ function multiSetWithRetry(data: OnyxMultiSetInput, retryAttempt?: number): Prom
return OnyxUtils.scheduleSubscriberUpdate(key, value);
});
- return Storage.multiSet(keyValuePairsToSet)
+ // Filter out the RAM-only key value pairs, as they should not be saved to storage
+ const keyValuePairsToStore = keyValuePairsToSet.filter(keyValuePair => !cache.isRamOnlyKey(keyValuePair[0]))
+
+ return Storage.multiSet(keyValuePairsToStore)
.catch((error) => OnyxUtils.retryOperation(error, multiSetWithRetry, newData, retryAttempt))
.then(() => {
OnyxUtils.sendActionToDevTools(OnyxUtils.METHOD.MULTI_SET, undefined, newData);
From d91820aedb61195b24033be4b4a9ab2074e3d6b0 Mon Sep 17 00:00:00 2001
From: Julian Kobrynski
Date: Tue, 27 Jan 2026 14:16:24 +0100
Subject: [PATCH 03/29] add RAM-only support to merge method
---
lib/OnyxMerge/index.native.ts | 3 ++-
lib/OnyxMerge/index.ts | 3 ++-
2 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/lib/OnyxMerge/index.native.ts b/lib/OnyxMerge/index.native.ts
index b796dfde..949c5a73 100644
--- a/lib/OnyxMerge/index.native.ts
+++ b/lib/OnyxMerge/index.native.ts
@@ -29,7 +29,8 @@ const applyMerge: ApplyMerge = , hasChanged);
// If the value has not changed, calling Storage.setItem() would be redundant and a waste of performance, so return early instead.
- if (!hasChanged) {
+ // If the key is marked as RAM-only, it should not be saved nor updated in the storage.
+ if (!hasChanged || cache.isRamOnlyKey(key)) {
return Promise.resolve({mergedValue, updatePromise});
}
diff --git a/lib/OnyxMerge/index.ts b/lib/OnyxMerge/index.ts
index 2a648499..4dda4104 100644
--- a/lib/OnyxMerge/index.ts
+++ b/lib/OnyxMerge/index.ts
@@ -21,7 +21,8 @@ const applyMerge: ApplyMerge = , hasChanged);
// If the value has not changed, calling Storage.setItem() would be redundant and a waste of performance, so return early instead.
- if (!hasChanged) {
+ // If the key is marked as RAM-only, it should not be saved nor updated in the storage.
+ if (!hasChanged || cache.isRamOnlyKey(key)) {
return Promise.resolve({mergedValue, updatePromise});
}
From ab3dd881f6d1871c0df4f82f5d60709d4051867e Mon Sep 17 00:00:00 2001
From: Julian Kobrynski
Date: Wed, 28 Jan 2026 09:35:26 +0100
Subject: [PATCH 04/29] add RAM-only support to clear method
---
lib/Onyx.ts | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/lib/Onyx.ts b/lib/Onyx.ts
index 7be47472..d9fad758 100644
--- a/lib/Onyx.ts
+++ b/lib/Onyx.ts
@@ -383,7 +383,11 @@ function clear(keysToPreserve: OnyxKey[] = []): Promise {
// Remove only the items that we want cleared from storage, and reset others to default
for (const key of keysToBeClearedFromStorage) cache.drop(key);
- return Storage.removeItems(keysToBeClearedFromStorage)
+
+ // Remove RAM-only keys value pairs as they are never saved to storage
+ const nonRamOnlyDefaultKeyValuePairs = keysToBeClearedFromStorage.filter(key => !cache.isRamOnlyKey(key))
+
+ return Storage.removeItems(nonRamOnlyDefaultKeyValuePairs)
.then(() => connectionManager.refreshSessionID())
.then(() => Storage.multiSet(defaultKeyValuePairs))
.then(() => {
From d4e975eb52f045f683c28238ed9ae9c802c1eeea Mon Sep 17 00:00:00 2001
From: Julian Kobrynski
Date: Wed, 28 Jan 2026 13:12:09 +0100
Subject: [PATCH 05/29] add ramOnlyKeys parameter to the init function, remove
RAM-only logic from initStoreValues
---
lib/Onyx.ts | 3 +++
lib/OnyxUtils.ts | 12 ------------
lib/types.ts | 6 ++++++
3 files changed, 9 insertions(+), 12 deletions(-)
diff --git a/lib/Onyx.ts b/lib/Onyx.ts
index d9fad758..1200e755 100644
--- a/lib/Onyx.ts
+++ b/lib/Onyx.ts
@@ -41,6 +41,7 @@ function init({
enablePerformanceMetrics = false,
enableDevTools = true,
skippableCollectionMemberIDs = [],
+ ramOnlyKeys = [],
}: InitOptions): void {
if (enablePerformanceMetrics) {
GlobalSettings.setPerformanceMetricsEnabled(true);
@@ -53,6 +54,8 @@ function init({
OnyxUtils.setSkippableCollectionMemberIDs(new Set(skippableCollectionMemberIDs));
+ cache.setRamOnlyKeys(new Set(ramOnlyKeys))
+
if (shouldSyncMultipleInstances) {
Storage.keepInstancesSync?.((key, value) => {
cache.set(key, value);
diff --git a/lib/OnyxUtils.ts b/lib/OnyxUtils.ts
index 42c32ac4..7badd8ba 100644
--- a/lib/OnyxUtils.ts
+++ b/lib/OnyxUtils.ts
@@ -84,9 +84,6 @@ let callbackToStateMapping: Record> = {}
// Keeps a copy of the values of the onyx collection keys as a map for faster lookups
let onyxCollectionKeySet = new Set();
-// Keeps a copy of the values of the onyx RAM-only keys as a map for faster lookups
-let onyxRamOnlyKeySet = new Set();
-
// Holds a mapping of the connected key to the subscriptionID for faster lookups
let onyxKeyToSubscriptionIDs = new Map();
@@ -169,12 +166,6 @@ function initStoreValues(keys: DeepRecord, initialKeyStates: Pa
return acc;
}, new Set());
- const ramOnlyValues = Object.values(keys.RAM_ONLY ?? {}) as string[];
- onyxRamOnlyKeySet = ramOnlyValues.reduce((acc, val) => {
- acc.add(val);
- return acc;
- }, new Set());
-
// Set our default key states to use when initializing and clearing Onyx data
defaultKeyStates = initialKeyStates;
@@ -186,9 +177,6 @@ function initStoreValues(keys: DeepRecord, initialKeyStates: Pa
// Set collection keys in cache for optimized storage
cache.setCollectionKeys(onyxCollectionKeySet);
- // Set RAM-only keys in cache for optimized storage
- cache.setRamOnlyKeys(onyxRamOnlyKeySet);
-
if (typeof keys.COLLECTION === 'object' && typeof keys.COLLECTION.SNAPSHOT === 'string') {
snapshotKey = keys.COLLECTION.SNAPSHOT;
}
diff --git a/lib/types.ts b/lib/types.ts
index 2cd4b75f..ac60354c 100644
--- a/lib/types.ts
+++ b/lib/types.ts
@@ -425,6 +425,12 @@ type InitOptions = {
* Additionally, any subscribers from these keys to won't receive any data from Onyx.
*/
skippableCollectionMemberIDs?: string[];
+
+ /**
+ * This is an array of keys that when provided to Onyx are flagged as RAM-only keys, that are not supposed to be saved to disk.
+ * This functionality replaces initWithStoredValues parameter from the useOnyx hook.
+ */
+ ramOnlyKeys?: OnyxKey[];
};
// eslint-disable-next-line @typescript-eslint/no-explicit-any
From 4889a470719b07cdc68fb9cc3c11a81ef97b4c41 Mon Sep 17 00:00:00 2001
From: Julian Kobrynski
Date: Wed, 28 Jan 2026 14:07:57 +0100
Subject: [PATCH 06/29] add RAM-only support to the clear method
---
lib/Onyx.ts | 7 ++-----
1 file changed, 2 insertions(+), 5 deletions(-)
diff --git a/lib/Onyx.ts b/lib/Onyx.ts
index 1200e755..59e6964b 100644
--- a/lib/Onyx.ts
+++ b/lib/Onyx.ts
@@ -376,7 +376,7 @@ function clear(keysToPreserve: OnyxKey[] = []): Promise {
const defaultKeyValuePairs = Object.entries(
Object.keys(defaultKeyStates)
- .filter((key) => !keysToPreserve.includes(key))
+ .filter((key) => !keysToPreserve.includes(key) && !cache.isRamOnlyKey(key))
.reduce((obj: KeyValueMapping, key) => {
// eslint-disable-next-line no-param-reassign
obj[key] = defaultKeyStates[key];
@@ -387,10 +387,7 @@ function clear(keysToPreserve: OnyxKey[] = []): Promise {
// Remove only the items that we want cleared from storage, and reset others to default
for (const key of keysToBeClearedFromStorage) cache.drop(key);
- // Remove RAM-only keys value pairs as they are never saved to storage
- const nonRamOnlyDefaultKeyValuePairs = keysToBeClearedFromStorage.filter(key => !cache.isRamOnlyKey(key))
-
- return Storage.removeItems(nonRamOnlyDefaultKeyValuePairs)
+ return Storage.removeItems(keysToBeClearedFromStorage)
.then(() => connectionManager.refreshSessionID())
.then(() => Storage.multiSet(defaultKeyValuePairs))
.then(() => {
From 17ecd7820052a122218a7177c7677b2a48284893 Mon Sep 17 00:00:00 2001
From: Julian Kobrynski
Date: Wed, 28 Jan 2026 15:41:28 +0100
Subject: [PATCH 07/29] add RAM-only support to methods that use
Storage.multiSet
---
lib/OnyxUtils.ts | 14 +++++++++++++-
1 file changed, 13 insertions(+), 1 deletion(-)
diff --git a/lib/OnyxUtils.ts b/lib/OnyxUtils.ts
index 7badd8ba..f5677a7c 100644
--- a/lib/OnyxUtils.ts
+++ b/lib/OnyxUtils.ts
@@ -1447,6 +1447,12 @@ function setCollectionWithRetry({collectionKey,
const updatePromise = OnyxUtils.scheduleNotifyCollectionSubscribers(collectionKey, mutableCollection, previousCollection);
+ // RAM-only keys are not supposed to be saved to storage
+ if(cache.isRamOnlyKey(collectionKey)) {
+ OnyxUtils.sendActionToDevTools(OnyxUtils.METHOD.SET_COLLECTION, undefined, mutableCollection);
+ return updatePromise;
+ }
+
return Storage.multiSet(keyValuePairs)
.catch((error) => OnyxUtils.retryOperation(error, setCollectionWithRetry, {collectionKey, collection}, retryAttempt))
.then(() => {
@@ -1561,7 +1567,8 @@ function mergeCollectionWithPatches(
promises.push(Storage.multiMerge(keyValuePairsForExistingCollection));
}
- if (keyValuePairsForNewCollection.length > 0) {
+ // We can skip this step for RAM-only keys as they should never be saved to storage
+ if (!cache.isRamOnlyKey(collectionKey) && keyValuePairsForNewCollection.length > 0) {
promises.push(Storage.multiSet(keyValuePairsForNewCollection));
}
@@ -1640,6 +1647,11 @@ function partialSetCollection({collectionKey, co
const updatePromise = scheduleNotifyCollectionSubscribers(collectionKey, mutableCollection, previousCollection);
+ if(cache.isRamOnlyKey(collectionKey)) {
+ sendActionToDevTools(METHOD.SET_COLLECTION, undefined, mutableCollection);
+ return updatePromise;
+ }
+
return Storage.multiSet(keyValuePairs)
.catch((error) => retryOperation(error, partialSetCollection, {collectionKey, collection}, retryAttempt))
.then(() => {
From 3ff81f749924b338cd7060d95bf19a1f1dc1b1f7 Mon Sep 17 00:00:00 2001
From: Julian Kobrynski
Date: Wed, 28 Jan 2026 15:45:10 +0100
Subject: [PATCH 08/29] add RAM-only support to methods that use
Storage.multiMerge
---
lib/OnyxUtils.ts | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/lib/OnyxUtils.ts b/lib/OnyxUtils.ts
index f5677a7c..e4e24174 100644
--- a/lib/OnyxUtils.ts
+++ b/lib/OnyxUtils.ts
@@ -1563,7 +1563,8 @@ function mergeCollectionWithPatches(
// New keys will be added via multiSet while existing keys will be updated using multiMerge
// This is because setting a key that doesn't exist yet with multiMerge will throw errors
- if (keyValuePairsForExistingCollection.length > 0) {
+ // We can skip this step for RAM-only keys as they should never be saved to storage
+ if (!cache.isRamOnlyKey(collectionKey) && keyValuePairsForExistingCollection.length > 0) {
promises.push(Storage.multiMerge(keyValuePairsForExistingCollection));
}
From df071121edac5c3e7638f6f9d2ad2a177f0ae478 Mon Sep 17 00:00:00 2001
From: Julian Kobrynski
Date: Wed, 28 Jan 2026 15:54:54 +0100
Subject: [PATCH 09/29] send RAM-only set actions to dev tools
---
lib/OnyxUtils.ts | 1 +
1 file changed, 1 insertion(+)
diff --git a/lib/OnyxUtils.ts b/lib/OnyxUtils.ts
index e4e24174..f75b2ff1 100644
--- a/lib/OnyxUtils.ts
+++ b/lib/OnyxUtils.ts
@@ -1322,6 +1322,7 @@ function setWithRetry({key, value, options}: SetParams
Date: Wed, 28 Jan 2026 16:14:25 +0100
Subject: [PATCH 10/29] add RAM-only support to setWithRetry for collection
child keys
---
lib/OnyxUtils.ts | 12 +++++++++++-
1 file changed, 11 insertions(+), 1 deletion(-)
diff --git a/lib/OnyxUtils.ts b/lib/OnyxUtils.ts
index f75b2ff1..28b33c2b 100644
--- a/lib/OnyxUtils.ts
+++ b/lib/OnyxUtils.ts
@@ -1321,7 +1321,17 @@ function setWithRetry({key, value, options}: SetParams
Date: Thu, 29 Jan 2026 11:38:09 +0100
Subject: [PATCH 11/29] add RAM-only support to multiSetWithRetry for
collection members
---
lib/OnyxUtils.ts | 16 ++++++++++++++--
1 file changed, 14 insertions(+), 2 deletions(-)
diff --git a/lib/OnyxUtils.ts b/lib/OnyxUtils.ts
index 28b33c2b..2a57640a 100644
--- a/lib/OnyxUtils.ts
+++ b/lib/OnyxUtils.ts
@@ -1386,8 +1386,20 @@ function multiSetWithRetry(data: OnyxMultiSetInput, retryAttempt?: number): Prom
return OnyxUtils.scheduleSubscriberUpdate(key, value);
});
- // Filter out the RAM-only key value pairs, as they should not be saved to storage
- const keyValuePairsToStore = keyValuePairsToSet.filter(keyValuePair => !cache.isRamOnlyKey(keyValuePair[0]))
+ const keyValuePairsToStore = keyValuePairsToSet.filter(keyValuePair => {
+ let collectionKey;
+ try {
+ const [key] = keyValuePair
+ collectionKey = OnyxUtils.splitCollectionMemberKey(key)[0];
+ } catch {
+ // The key is not a collection key
+ }
+
+ const isMemberOfRamOnlyCollection = collectionKey && cache.isRamOnlyKey(collectionKey)
+
+ // Filter out the RAM-only key value pairs, as they should not be saved to storage
+ return !cache.isRamOnlyKey(keyValuePair[0]) && !isMemberOfRamOnlyCollection
+ })
return Storage.multiSet(keyValuePairsToStore)
.catch((error) => OnyxUtils.retryOperation(error, multiSetWithRetry, newData, retryAttempt))
From ddfc69475c296ea6b55eecaacbdba8583a4f41e3 Mon Sep 17 00:00:00 2001
From: Julian Kobrynski
Date: Thu, 29 Jan 2026 14:53:46 +0100
Subject: [PATCH 12/29] cleanup the code
---
lib/Onyx.ts | 2 +-
lib/OnyxMerge/index.native.ts | 2 +-
lib/OnyxMerge/index.ts | 2 +-
lib/OnyxUtils.ts | 59 ++++++++++++++++++++---------------
4 files changed, 37 insertions(+), 28 deletions(-)
diff --git a/lib/Onyx.ts b/lib/Onyx.ts
index 59e6964b..8710f2a9 100644
--- a/lib/Onyx.ts
+++ b/lib/Onyx.ts
@@ -376,7 +376,7 @@ function clear(keysToPreserve: OnyxKey[] = []): Promise {
const defaultKeyValuePairs = Object.entries(
Object.keys(defaultKeyStates)
- .filter((key) => !keysToPreserve.includes(key) && !cache.isRamOnlyKey(key))
+ .filter((key) => !keysToPreserve.includes(key) && !OnyxUtils.isRamOnlyKey(key) && !OnyxUtils.isRamOnlyCollectionMember(key))
.reduce((obj: KeyValueMapping, key) => {
// eslint-disable-next-line no-param-reassign
obj[key] = defaultKeyStates[key];
diff --git a/lib/OnyxMerge/index.native.ts b/lib/OnyxMerge/index.native.ts
index 949c5a73..c068c8f9 100644
--- a/lib/OnyxMerge/index.native.ts
+++ b/lib/OnyxMerge/index.native.ts
@@ -30,7 +30,7 @@ const applyMerge: ApplyMerge = ({key, value, options}: SetParams {
- let collectionKey;
- try {
- const [key] = keyValuePair
- collectionKey = OnyxUtils.splitCollectionMemberKey(key)[0];
- } catch {
- // The key is not a collection key
- }
-
- const isMemberOfRamOnlyCollection = collectionKey && cache.isRamOnlyKey(collectionKey)
-
+ const [key] = keyValuePair
// Filter out the RAM-only key value pairs, as they should not be saved to storage
- return !cache.isRamOnlyKey(keyValuePair[0]) && !isMemberOfRamOnlyCollection
+ return !isRamOnlyKey(keyValuePair[0]) && !isRamOnlyCollectionMember(key)
})
return Storage.multiSet(keyValuePairsToStore)
@@ -1471,7 +1478,7 @@ function setCollectionWithRetry({collectionKey,
const updatePromise = OnyxUtils.scheduleNotifyCollectionSubscribers(collectionKey, mutableCollection, previousCollection);
// RAM-only keys are not supposed to be saved to storage
- if(cache.isRamOnlyKey(collectionKey)) {
+ if(isRamOnlyKey(collectionKey)) {
OnyxUtils.sendActionToDevTools(OnyxUtils.METHOD.SET_COLLECTION, undefined, mutableCollection);
return updatePromise;
}
@@ -1587,12 +1594,12 @@ function mergeCollectionWithPatches(
// New keys will be added via multiSet while existing keys will be updated using multiMerge
// This is because setting a key that doesn't exist yet with multiMerge will throw errors
// We can skip this step for RAM-only keys as they should never be saved to storage
- if (!cache.isRamOnlyKey(collectionKey) && keyValuePairsForExistingCollection.length > 0) {
+ if (!isRamOnlyKey(collectionKey) && keyValuePairsForExistingCollection.length > 0) {
promises.push(Storage.multiMerge(keyValuePairsForExistingCollection));
}
// We can skip this step for RAM-only keys as they should never be saved to storage
- if (!cache.isRamOnlyKey(collectionKey) && keyValuePairsForNewCollection.length > 0) {
+ if (!isRamOnlyKey(collectionKey) && keyValuePairsForNewCollection.length > 0) {
promises.push(Storage.multiSet(keyValuePairsForNewCollection));
}
@@ -1671,7 +1678,7 @@ function partialSetCollection({collectionKey, co
const updatePromise = scheduleNotifyCollectionSubscribers(collectionKey, mutableCollection, previousCollection);
- if(cache.isRamOnlyKey(collectionKey)) {
+ if(isRamOnlyKey(collectionKey)) {
sendActionToDevTools(METHOD.SET_COLLECTION, undefined, mutableCollection);
return updatePromise;
}
@@ -1759,6 +1766,8 @@ const OnyxUtils = {
setWithRetry,
multiSetWithRetry,
setCollectionWithRetry,
+ isRamOnlyKey,
+ isRamOnlyCollectionMember
};
GlobalSettings.addGlobalSettingsChangeListener(({enablePerformanceMetrics}) => {
From a492c412160bffaeacc496093299862cf84f0ab9 Mon Sep 17 00:00:00 2001
From: Julian Kobrynski
Date: Thu, 29 Jan 2026 15:09:46 +0100
Subject: [PATCH 13/29] update the docs
---
API-INTERNAL.md | 6 ++++++
README.md | 18 ++++++++++++++++++
2 files changed, 24 insertions(+)
diff --git a/API-INTERNAL.md b/API-INTERNAL.md
index 4e29291a..9762e610 100644
--- a/API-INTERNAL.md
+++ b/API-INTERNAL.md
@@ -58,6 +58,12 @@ is associated with a collection of keys.
isCollectionMember(key) ⇒
Checks if a given key is a collection member key (not just a collection key).
+isRamOnlyKey(key) ⇒
+Checks if a given key is a RAM-only key.
+
+isRamOnlyCollectionMember(key) ⇒
+Checks if a given key is a member of a RAM-only collection.
+
splitCollectionMemberKey(key, collectionKey) ⇒
Splits a collection member key into the collection key part and the ID part.
diff --git a/README.md b/README.md
index de71666f..30f36564 100644
--- a/README.md
+++ b/README.md
@@ -460,6 +460,24 @@ Onyx.init({
});
```
+### Using RAM-only keys
+
+You can choose not to save certain keys on disk and keep them RAM-only, that way their values will reset with each session. It also works for collections, you just have to pass an array of `ramOnlyKeys` to the `Onyx.init` method.
+
+```javascript
+import Onyx from 'react-native-onyx';
+
+Onyx.init({
+ keys: ONYXKEYS,
+ ramOnlyKeys: [
+ ONYXKEYS.RAM_ONLY_KEY_1,
+ ONYXKEYS.RAM_ONLY_KEY_2,
+ ],
+});
+```
+
+You can achieve a similar effect using `initWithStoredValues: false` in `useOnyx`, but that feature is deprecated and will be removed in one of the future releases.
+
### Usage
The extension interface is pretty simple, on the left sidebar you can see all the updates made to the local storage, in ascending order, and on the right pane you can see the whole the current state, payload of an action and the diff between the previous state and the current state after the action was triggered.
From aa5f13b3748fc46a054c5bf605c8a4f6b1d659b5 Mon Sep 17 00:00:00 2001
From: Julian Kobrynski
Date: Fri, 30 Jan 2026 11:13:18 +0100
Subject: [PATCH 14/29] add unit tests to newly added logic
---
tests/unit/onyxCacheTest.tsx | 20 +++++++
tests/unit/onyxTest.ts | 111 +++++++++++++++++++++++++++++++++++
2 files changed, 131 insertions(+)
diff --git a/tests/unit/onyxCacheTest.tsx b/tests/unit/onyxCacheTest.tsx
index ae871f9b..b988eaa2 100644
--- a/tests/unit/onyxCacheTest.tsx
+++ b/tests/unit/onyxCacheTest.tsx
@@ -661,5 +661,25 @@ describe('Onyx', () => {
expect(cache.hasCacheForKey(triggerKey)).toBe(true);
});
});
+
+ it('should save RAM-only keys', () => {
+ const testKeys = {
+ ...ONYX_KEYS,
+ COLLECTION: {
+ ...ONYX_KEYS.COLLECTION,
+ RAM_ONLY_COLLECTION: 'ramOnlyCollection'
+ },
+ RAM_ONLY_KEY: 'ramOnlyKey'
+ }
+
+ return initOnyx({
+ keys: testKeys,
+ ramOnlyKeys: [testKeys.COLLECTION.RAM_ONLY_COLLECTION, testKeys.RAM_ONLY_KEY]
+ }).then(() => {
+ expect(cache.isRamOnlyKey(testKeys.RAM_ONLY_KEY)).toBeTruthy()
+ expect(cache.isRamOnlyKey(testKeys.COLLECTION.RAM_ONLY_COLLECTION)).toBeTruthy()
+ expect(cache.isRamOnlyKey(testKeys.TEST_KEY)).toBeFalsy()
+ })
+ })
});
});
diff --git a/tests/unit/onyxTest.ts b/tests/unit/onyxTest.ts
index b432bf82..4ee8309b 100644
--- a/tests/unit/onyxTest.ts
+++ b/tests/unit/onyxTest.ts
@@ -24,7 +24,9 @@ const ONYX_KEYS = {
ANIMALS: 'animals_',
SNAPSHOT: 'snapshot_',
ROUTES: 'routes_',
+ RAM_ONLY_COLLECTION: 'ramOnlyCollection_'
},
+ RAM_ONLY_TEST_KEY: 'ramOnlyKey'
};
Onyx.init({
@@ -33,6 +35,10 @@ Onyx.init({
[ONYX_KEYS.OTHER_TEST]: 42,
[ONYX_KEYS.KEY_WITH_UNDERSCORE]: 'default',
},
+ ramOnlyKeys: [
+ ONYX_KEYS.RAM_ONLY_TEST_KEY,
+ ONYX_KEYS.COLLECTION.RAM_ONLY_COLLECTION
+ ],
skippableCollectionMemberIDs: ['skippable-id'],
});
@@ -2181,6 +2187,24 @@ describe('Onyx', () => {
[`${ONYX_KEYS.COLLECTION.TEST_UPDATE}entry2`, entry2ExpectedResult],
]);
});
+
+ it('should not save a RAM-only collection to storage', async () => {
+ const key1 = `${ONYX_KEYS.COLLECTION.RAM_ONLY_COLLECTION}1`
+ const key2 = `${ONYX_KEYS.COLLECTION.RAM_ONLY_COLLECTION}2`
+
+ await Onyx.mergeCollection(ONYX_KEYS.COLLECTION.RAM_ONLY_COLLECTION, {
+ [key1]: 'value 1',
+ [key2]: 'value 2',
+ })
+
+ await Onyx.mergeCollection(ONYX_KEYS.COLLECTION.RAM_ONLY_COLLECTION, {
+ [key1]: 'updated value 1',
+ [key2]: 'updated value 2',
+ })
+
+ expect(await StorageMock.getItem(key1)).toBeNull()
+ expect(await StorageMock.getItem(key2)).toBeNull()
+ })
});
});
@@ -2332,6 +2356,50 @@ describe('Onyx', () => {
Onyx.disconnect(connection1);
Onyx.disconnect(connection2);
});
+
+ it('should not save a RAM-only collection to storage', async () => {
+ const entry1 = 'test 1'
+
+ const entry2 = 'test 2'
+
+ await Onyx.multiSet({[`${ONYX_KEYS.COLLECTION.RAM_ONLY_COLLECTION}1`]: entry1});
+ await Onyx.multiSet({[`${ONYX_KEYS.COLLECTION.RAM_ONLY_COLLECTION}2`]: entry2});
+
+ const queuedUpdates: Array> = [];
+
+ queuedUpdates.push(
+ {
+ key: `${ONYX_KEYS.COLLECTION.RAM_ONLY_COLLECTION}1`,
+ onyxMethod: 'merge',
+ value: null
+ },
+ {
+ key: `${ONYX_KEYS.COLLECTION.RAM_ONLY_COLLECTION}2`,
+ onyxMethod: 'merge',
+ value: null
+ },
+ );
+
+ queuedUpdates.push(
+ {
+ key: `${ONYX_KEYS.COLLECTION.RAM_ONLY_COLLECTION}1`,
+ onyxMethod: 'merge',
+ value: 'updated test 1'
+ },
+ {
+ key: `${ONYX_KEYS.COLLECTION.RAM_ONLY_COLLECTION}2`,
+ onyxMethod: 'merge',
+ value: 'updated test 2'
+ },
+ );
+
+ await Onyx.update(queuedUpdates);
+
+ expect(true).toBeTruthy()
+
+ expect(await StorageMock.getItem(`${ONYX_KEYS.COLLECTION.RAM_ONLY_COLLECTION}1`)).toBeNull()
+ expect(await StorageMock.getItem(`${ONYX_KEYS.COLLECTION.RAM_ONLY_COLLECTION}2`)).toBeNull()
+ });
});
describe('merge', () => {
@@ -2587,8 +2655,38 @@ describe('Onyx', () => {
expect(testKeyValue).toEqual(testData);
});
});
+
+ it('should not save a RAM-only key to storage', async () => {
+ await Onyx.set(ONYX_KEYS.RAM_ONLY_TEST_KEY, 'test')
+
+ expect(await StorageMock.getItem(ONYX_KEYS.RAM_ONLY_TEST_KEY)).toBeNull()
+ })
+
+ it('should not save a member of a RAM-only collection to storage', async () => {
+ const collectionMemberKey = `${ONYX_KEYS.COLLECTION.RAM_ONLY_COLLECTION}1`
+ await Onyx.set(collectionMemberKey, 'test')
+
+ expect(await StorageMock.getItem(collectionMemberKey)).toBeNull()
+ })
});
+ describe('multiSet', () => {
+ it('should only save non RAM-only keys to storage', async () => {
+ const otherTestValue = 'non ram only value'
+ const collectionMemberKey = `${ONYX_KEYS.COLLECTION.RAM_ONLY_COLLECTION}2`
+
+ await Onyx.multiSet({
+ [ONYX_KEYS.OTHER_TEST]: otherTestValue,
+ [ONYX_KEYS.RAM_ONLY_TEST_KEY]: 'test value',
+ [collectionMemberKey]: 'test value',
+ })
+
+ expect(await StorageMock.getItem(ONYX_KEYS.OTHER_TEST)).toEqual(otherTestValue)
+ expect(await StorageMock.getItem(ONYX_KEYS.RAM_ONLY_TEST_KEY)).toBeNull()
+ expect(await StorageMock.getItem(collectionMemberKey)).toBeNull()
+ })
+ })
+
describe('setCollection', () => {
it('should replace all existing collection members with new values and remove old ones', async () => {
let result: OnyxCollection;
@@ -2702,6 +2800,19 @@ describe('Onyx', () => {
[routeB]: {name: 'Route B'},
});
});
+
+ it('should not save a RAM-only collection to storage', async () => {
+ const key1 = `${ONYX_KEYS.COLLECTION.RAM_ONLY_COLLECTION}1`
+ const key2 = `${ONYX_KEYS.COLLECTION.RAM_ONLY_COLLECTION}2`
+
+ await Onyx.setCollection(ONYX_KEYS.COLLECTION.RAM_ONLY_COLLECTION, {
+ [key1]: 'test1',
+ [key2]: 'test2',
+ })
+
+ expect(await StorageMock.getItem(key1)).toBeNull()
+ expect(await StorageMock.getItem(key2)).toBeNull()
+ })
});
describe('skippable collection member ids', () => {
From 091bf1b1b62b0b45695bf0753dd0fe91aeeb3312 Mon Sep 17 00:00:00 2001
From: Julian Kobrynski
Date: Fri, 30 Jan 2026 14:17:02 +0100
Subject: [PATCH 15/29] address review comments
---
lib/Onyx.ts | 1 -
lib/OnyxMerge/index.native.ts | 4 +++-
lib/OnyxMerge/index.ts | 4 +++-
3 files changed, 6 insertions(+), 3 deletions(-)
diff --git a/lib/Onyx.ts b/lib/Onyx.ts
index 8710f2a9..0b434241 100644
--- a/lib/Onyx.ts
+++ b/lib/Onyx.ts
@@ -386,7 +386,6 @@ function clear(keysToPreserve: OnyxKey[] = []): Promise {
// Remove only the items that we want cleared from storage, and reset others to default
for (const key of keysToBeClearedFromStorage) cache.drop(key);
-
return Storage.removeItems(keysToBeClearedFromStorage)
.then(() => connectionManager.refreshSessionID())
.then(() => Storage.multiSet(defaultKeyValuePairs))
diff --git a/lib/OnyxMerge/index.native.ts b/lib/OnyxMerge/index.native.ts
index c068c8f9..1b069473 100644
--- a/lib/OnyxMerge/index.native.ts
+++ b/lib/OnyxMerge/index.native.ts
@@ -28,9 +28,11 @@ const applyMerge: ApplyMerge = , hasChanged);
+ const shouldSkipStorageOperations = !hasChanged || OnyxUtils.isRamOnlyKey(key) || OnyxUtils.isRamOnlyCollectionMember(key)
+
// If the value has not changed, calling Storage.setItem() would be redundant and a waste of performance, so return early instead.
// If the key is marked as RAM-only, it should not be saved nor updated in the storage.
- if (!hasChanged || OnyxUtils.isRamOnlyKey(key) || OnyxUtils.isRamOnlyCollectionMember(key)) {
+ if (shouldSkipStorageOperations) {
return Promise.resolve({mergedValue, updatePromise});
}
diff --git a/lib/OnyxMerge/index.ts b/lib/OnyxMerge/index.ts
index 1570a3a0..131740bc 100644
--- a/lib/OnyxMerge/index.ts
+++ b/lib/OnyxMerge/index.ts
@@ -20,9 +20,11 @@ const applyMerge: ApplyMerge = , hasChanged);
+ const shouldSkipStorageOperations = !hasChanged || OnyxUtils.isRamOnlyKey(key) || OnyxUtils.isRamOnlyCollectionMember(key)
+
// If the value has not changed, calling Storage.setItem() would be redundant and a waste of performance, so return early instead.
// If the key is marked as RAM-only, it should not be saved nor updated in the storage.
- if (!hasChanged || OnyxUtils.isRamOnlyKey(key) || OnyxUtils.isRamOnlyCollectionMember(key)) {
+ if (shouldSkipStorageOperations) {
return Promise.resolve({mergedValue, updatePromise});
}
From 3b25980efa265d935fd7a74044515e8aaa0d7ace Mon Sep 17 00:00:00 2001
From: Julian Kobrynski
Date: Fri, 30 Jan 2026 14:19:26 +0100
Subject: [PATCH 16/29] prettier
---
lib/Onyx.ts | 2 +-
lib/OnyxCache.ts | 2 +-
lib/OnyxMerge/index.native.ts | 4 +-
lib/OnyxMerge/index.ts | 4 +-
lib/OnyxUtils.ts | 32 ++++++-------
lib/types.ts | 2 +-
tests/unit/onyxCacheTest.tsx | 18 ++++----
tests/unit/onyxTest.ts | 85 +++++++++++++++++------------------
8 files changed, 73 insertions(+), 76 deletions(-)
diff --git a/lib/Onyx.ts b/lib/Onyx.ts
index 0b434241..4b9af623 100644
--- a/lib/Onyx.ts
+++ b/lib/Onyx.ts
@@ -54,7 +54,7 @@ function init({
OnyxUtils.setSkippableCollectionMemberIDs(new Set(skippableCollectionMemberIDs));
- cache.setRamOnlyKeys(new Set(ramOnlyKeys))
+ cache.setRamOnlyKeys(new Set(ramOnlyKeys));
if (shouldSyncMultipleInstances) {
Storage.keepInstancesSync?.((key, value) => {
diff --git a/lib/OnyxCache.ts b/lib/OnyxCache.ts
index e40dccbe..aa6d670d 100644
--- a/lib/OnyxCache.ts
+++ b/lib/OnyxCache.ts
@@ -98,7 +98,7 @@ class OnyxCache {
'getCollectionKey',
'getCollectionData',
'setRamOnlyKeys',
- 'isRamOnlyKey'
+ 'isRamOnlyKey',
);
}
diff --git a/lib/OnyxMerge/index.native.ts b/lib/OnyxMerge/index.native.ts
index 1b069473..27d4416d 100644
--- a/lib/OnyxMerge/index.native.ts
+++ b/lib/OnyxMerge/index.native.ts
@@ -28,8 +28,8 @@ const applyMerge: ApplyMerge = , hasChanged);
- const shouldSkipStorageOperations = !hasChanged || OnyxUtils.isRamOnlyKey(key) || OnyxUtils.isRamOnlyCollectionMember(key)
-
+ const shouldSkipStorageOperations = !hasChanged || OnyxUtils.isRamOnlyKey(key) || OnyxUtils.isRamOnlyCollectionMember(key);
+
// If the value has not changed, calling Storage.setItem() would be redundant and a waste of performance, so return early instead.
// If the key is marked as RAM-only, it should not be saved nor updated in the storage.
if (shouldSkipStorageOperations) {
diff --git a/lib/OnyxMerge/index.ts b/lib/OnyxMerge/index.ts
index 131740bc..2ff24d97 100644
--- a/lib/OnyxMerge/index.ts
+++ b/lib/OnyxMerge/index.ts
@@ -20,8 +20,8 @@ const applyMerge: ApplyMerge = , hasChanged);
- const shouldSkipStorageOperations = !hasChanged || OnyxUtils.isRamOnlyKey(key) || OnyxUtils.isRamOnlyCollectionMember(key)
-
+ const shouldSkipStorageOperations = !hasChanged || OnyxUtils.isRamOnlyKey(key) || OnyxUtils.isRamOnlyCollectionMember(key);
+
// If the value has not changed, calling Storage.setItem() would be redundant and a waste of performance, so return early instead.
// If the key is marked as RAM-only, it should not be saved nor updated in the storage.
if (shouldSkipStorageOperations) {
diff --git a/lib/OnyxUtils.ts b/lib/OnyxUtils.ts
index d3a641e4..e7b991fc 100644
--- a/lib/OnyxUtils.ts
+++ b/lib/OnyxUtils.ts
@@ -456,12 +456,12 @@ function isCollectionMember(key: OnyxKey): boolean {
}
/**
- * Checks if a given key is a RAM-only key
+ * Checks if a given key is a RAM-only key
* @param key - The key to check
* @returns true if key is a RAM-only key
*/
function isRamOnlyKey(key: OnyxKey): boolean {
- return cache.isRamOnlyKey(key)
+ return cache.isRamOnlyKey(key);
}
/**
@@ -471,12 +471,12 @@ function isRamOnlyKey(key: OnyxKey): boolean {
*/
function isRamOnlyCollectionMember(key: OnyxKey): boolean {
try {
- const collectionKey = getCollectionKey(key)
+ const collectionKey = getCollectionKey(key);
// If collectionKey exists for a given key, check if it's a RAM-only key
- return isRamOnlyKey(collectionKey)
+ return isRamOnlyKey(collectionKey);
} catch {
// If getCollectionKey throws, the key is not a collection member
- return false
+ return false;
}
}
@@ -1347,10 +1347,10 @@ function setWithRetry({key, value, options}: SetParams OnyxUtils.retryOperation(error, setWithRetry, {key, value: valueWithoutNestedNullValues, options}, retryAttempt))
@@ -1402,12 +1402,12 @@ function multiSetWithRetry(data: OnyxMultiSetInput, retryAttempt?: number): Prom
return OnyxUtils.scheduleSubscriberUpdate(key, value);
});
- const keyValuePairsToStore = keyValuePairsToSet.filter(keyValuePair => {
- const [key] = keyValuePair
+ const keyValuePairsToStore = keyValuePairsToSet.filter((keyValuePair) => {
+ const [key] = keyValuePair;
// Filter out the RAM-only key value pairs, as they should not be saved to storage
- return !isRamOnlyKey(keyValuePair[0]) && !isRamOnlyCollectionMember(key)
- })
-
+ return !isRamOnlyKey(keyValuePair[0]) && !isRamOnlyCollectionMember(key);
+ });
+
return Storage.multiSet(keyValuePairsToStore)
.catch((error) => OnyxUtils.retryOperation(error, multiSetWithRetry, newData, retryAttempt))
.then(() => {
@@ -1478,7 +1478,7 @@ function setCollectionWithRetry({collectionKey,
const updatePromise = OnyxUtils.scheduleNotifyCollectionSubscribers(collectionKey, mutableCollection, previousCollection);
// RAM-only keys are not supposed to be saved to storage
- if(isRamOnlyKey(collectionKey)) {
+ if (isRamOnlyKey(collectionKey)) {
OnyxUtils.sendActionToDevTools(OnyxUtils.METHOD.SET_COLLECTION, undefined, mutableCollection);
return updatePromise;
}
@@ -1678,7 +1678,7 @@ function partialSetCollection({collectionKey, co
const updatePromise = scheduleNotifyCollectionSubscribers(collectionKey, mutableCollection, previousCollection);
- if(isRamOnlyKey(collectionKey)) {
+ if (isRamOnlyKey(collectionKey)) {
sendActionToDevTools(METHOD.SET_COLLECTION, undefined, mutableCollection);
return updatePromise;
}
@@ -1767,7 +1767,7 @@ const OnyxUtils = {
multiSetWithRetry,
setCollectionWithRetry,
isRamOnlyKey,
- isRamOnlyCollectionMember
+ isRamOnlyCollectionMember,
};
GlobalSettings.addGlobalSettingsChangeListener(({enablePerformanceMetrics}) => {
diff --git a/lib/types.ts b/lib/types.ts
index ac60354c..ad421c3b 100644
--- a/lib/types.ts
+++ b/lib/types.ts
@@ -427,7 +427,7 @@ type InitOptions = {
skippableCollectionMemberIDs?: string[];
/**
- * This is an array of keys that when provided to Onyx are flagged as RAM-only keys, that are not supposed to be saved to disk.
+ * This is an array of keys that when provided to Onyx are flagged as RAM-only keys, that are not supposed to be saved to disk.
* This functionality replaces initWithStoredValues parameter from the useOnyx hook.
*/
ramOnlyKeys?: OnyxKey[];
diff --git a/tests/unit/onyxCacheTest.tsx b/tests/unit/onyxCacheTest.tsx
index b988eaa2..5f215428 100644
--- a/tests/unit/onyxCacheTest.tsx
+++ b/tests/unit/onyxCacheTest.tsx
@@ -667,19 +667,19 @@ describe('Onyx', () => {
...ONYX_KEYS,
COLLECTION: {
...ONYX_KEYS.COLLECTION,
- RAM_ONLY_COLLECTION: 'ramOnlyCollection'
+ RAM_ONLY_COLLECTION: 'ramOnlyCollection',
},
- RAM_ONLY_KEY: 'ramOnlyKey'
- }
+ RAM_ONLY_KEY: 'ramOnlyKey',
+ };
return initOnyx({
keys: testKeys,
- ramOnlyKeys: [testKeys.COLLECTION.RAM_ONLY_COLLECTION, testKeys.RAM_ONLY_KEY]
+ ramOnlyKeys: [testKeys.COLLECTION.RAM_ONLY_COLLECTION, testKeys.RAM_ONLY_KEY],
}).then(() => {
- expect(cache.isRamOnlyKey(testKeys.RAM_ONLY_KEY)).toBeTruthy()
- expect(cache.isRamOnlyKey(testKeys.COLLECTION.RAM_ONLY_COLLECTION)).toBeTruthy()
- expect(cache.isRamOnlyKey(testKeys.TEST_KEY)).toBeFalsy()
- })
- })
+ expect(cache.isRamOnlyKey(testKeys.RAM_ONLY_KEY)).toBeTruthy();
+ expect(cache.isRamOnlyKey(testKeys.COLLECTION.RAM_ONLY_COLLECTION)).toBeTruthy();
+ expect(cache.isRamOnlyKey(testKeys.TEST_KEY)).toBeFalsy();
+ });
+ });
});
});
diff --git a/tests/unit/onyxTest.ts b/tests/unit/onyxTest.ts
index 4ee8309b..474beef2 100644
--- a/tests/unit/onyxTest.ts
+++ b/tests/unit/onyxTest.ts
@@ -24,9 +24,9 @@ const ONYX_KEYS = {
ANIMALS: 'animals_',
SNAPSHOT: 'snapshot_',
ROUTES: 'routes_',
- RAM_ONLY_COLLECTION: 'ramOnlyCollection_'
+ RAM_ONLY_COLLECTION: 'ramOnlyCollection_',
},
- RAM_ONLY_TEST_KEY: 'ramOnlyKey'
+ RAM_ONLY_TEST_KEY: 'ramOnlyKey',
};
Onyx.init({
@@ -35,10 +35,7 @@ Onyx.init({
[ONYX_KEYS.OTHER_TEST]: 42,
[ONYX_KEYS.KEY_WITH_UNDERSCORE]: 'default',
},
- ramOnlyKeys: [
- ONYX_KEYS.RAM_ONLY_TEST_KEY,
- ONYX_KEYS.COLLECTION.RAM_ONLY_COLLECTION
- ],
+ ramOnlyKeys: [ONYX_KEYS.RAM_ONLY_TEST_KEY, ONYX_KEYS.COLLECTION.RAM_ONLY_COLLECTION],
skippableCollectionMemberIDs: ['skippable-id'],
});
@@ -2189,22 +2186,22 @@ describe('Onyx', () => {
});
it('should not save a RAM-only collection to storage', async () => {
- const key1 = `${ONYX_KEYS.COLLECTION.RAM_ONLY_COLLECTION}1`
- const key2 = `${ONYX_KEYS.COLLECTION.RAM_ONLY_COLLECTION}2`
+ const key1 = `${ONYX_KEYS.COLLECTION.RAM_ONLY_COLLECTION}1`;
+ const key2 = `${ONYX_KEYS.COLLECTION.RAM_ONLY_COLLECTION}2`;
await Onyx.mergeCollection(ONYX_KEYS.COLLECTION.RAM_ONLY_COLLECTION, {
[key1]: 'value 1',
[key2]: 'value 2',
- })
+ });
await Onyx.mergeCollection(ONYX_KEYS.COLLECTION.RAM_ONLY_COLLECTION, {
[key1]: 'updated value 1',
[key2]: 'updated value 2',
- })
+ });
- expect(await StorageMock.getItem(key1)).toBeNull()
- expect(await StorageMock.getItem(key2)).toBeNull()
- })
+ expect(await StorageMock.getItem(key1)).toBeNull();
+ expect(await StorageMock.getItem(key2)).toBeNull();
+ });
});
});
@@ -2358,10 +2355,10 @@ describe('Onyx', () => {
});
it('should not save a RAM-only collection to storage', async () => {
- const entry1 = 'test 1'
+ const entry1 = 'test 1';
+
+ const entry2 = 'test 2';
- const entry2 = 'test 2'
-
await Onyx.multiSet({[`${ONYX_KEYS.COLLECTION.RAM_ONLY_COLLECTION}1`]: entry1});
await Onyx.multiSet({[`${ONYX_KEYS.COLLECTION.RAM_ONLY_COLLECTION}2`]: entry2});
@@ -2371,12 +2368,12 @@ describe('Onyx', () => {
{
key: `${ONYX_KEYS.COLLECTION.RAM_ONLY_COLLECTION}1`,
onyxMethod: 'merge',
- value: null
+ value: null,
},
{
key: `${ONYX_KEYS.COLLECTION.RAM_ONLY_COLLECTION}2`,
onyxMethod: 'merge',
- value: null
+ value: null,
},
);
@@ -2384,21 +2381,21 @@ describe('Onyx', () => {
{
key: `${ONYX_KEYS.COLLECTION.RAM_ONLY_COLLECTION}1`,
onyxMethod: 'merge',
- value: 'updated test 1'
+ value: 'updated test 1',
},
{
key: `${ONYX_KEYS.COLLECTION.RAM_ONLY_COLLECTION}2`,
onyxMethod: 'merge',
- value: 'updated test 2'
+ value: 'updated test 2',
},
);
await Onyx.update(queuedUpdates);
- expect(true).toBeTruthy()
+ expect(true).toBeTruthy();
- expect(await StorageMock.getItem(`${ONYX_KEYS.COLLECTION.RAM_ONLY_COLLECTION}1`)).toBeNull()
- expect(await StorageMock.getItem(`${ONYX_KEYS.COLLECTION.RAM_ONLY_COLLECTION}2`)).toBeNull()
+ expect(await StorageMock.getItem(`${ONYX_KEYS.COLLECTION.RAM_ONLY_COLLECTION}1`)).toBeNull();
+ expect(await StorageMock.getItem(`${ONYX_KEYS.COLLECTION.RAM_ONLY_COLLECTION}2`)).toBeNull();
});
});
@@ -2657,35 +2654,35 @@ describe('Onyx', () => {
});
it('should not save a RAM-only key to storage', async () => {
- await Onyx.set(ONYX_KEYS.RAM_ONLY_TEST_KEY, 'test')
+ await Onyx.set(ONYX_KEYS.RAM_ONLY_TEST_KEY, 'test');
- expect(await StorageMock.getItem(ONYX_KEYS.RAM_ONLY_TEST_KEY)).toBeNull()
- })
+ expect(await StorageMock.getItem(ONYX_KEYS.RAM_ONLY_TEST_KEY)).toBeNull();
+ });
it('should not save a member of a RAM-only collection to storage', async () => {
- const collectionMemberKey = `${ONYX_KEYS.COLLECTION.RAM_ONLY_COLLECTION}1`
- await Onyx.set(collectionMemberKey, 'test')
+ const collectionMemberKey = `${ONYX_KEYS.COLLECTION.RAM_ONLY_COLLECTION}1`;
+ await Onyx.set(collectionMemberKey, 'test');
- expect(await StorageMock.getItem(collectionMemberKey)).toBeNull()
- })
+ expect(await StorageMock.getItem(collectionMemberKey)).toBeNull();
+ });
});
describe('multiSet', () => {
it('should only save non RAM-only keys to storage', async () => {
- const otherTestValue = 'non ram only value'
- const collectionMemberKey = `${ONYX_KEYS.COLLECTION.RAM_ONLY_COLLECTION}2`
+ const otherTestValue = 'non ram only value';
+ const collectionMemberKey = `${ONYX_KEYS.COLLECTION.RAM_ONLY_COLLECTION}2`;
await Onyx.multiSet({
[ONYX_KEYS.OTHER_TEST]: otherTestValue,
[ONYX_KEYS.RAM_ONLY_TEST_KEY]: 'test value',
[collectionMemberKey]: 'test value',
- })
+ });
- expect(await StorageMock.getItem(ONYX_KEYS.OTHER_TEST)).toEqual(otherTestValue)
- expect(await StorageMock.getItem(ONYX_KEYS.RAM_ONLY_TEST_KEY)).toBeNull()
- expect(await StorageMock.getItem(collectionMemberKey)).toBeNull()
- })
- })
+ expect(await StorageMock.getItem(ONYX_KEYS.OTHER_TEST)).toEqual(otherTestValue);
+ expect(await StorageMock.getItem(ONYX_KEYS.RAM_ONLY_TEST_KEY)).toBeNull();
+ expect(await StorageMock.getItem(collectionMemberKey)).toBeNull();
+ });
+ });
describe('setCollection', () => {
it('should replace all existing collection members with new values and remove old ones', async () => {
@@ -2802,17 +2799,17 @@ describe('Onyx', () => {
});
it('should not save a RAM-only collection to storage', async () => {
- const key1 = `${ONYX_KEYS.COLLECTION.RAM_ONLY_COLLECTION}1`
- const key2 = `${ONYX_KEYS.COLLECTION.RAM_ONLY_COLLECTION}2`
+ const key1 = `${ONYX_KEYS.COLLECTION.RAM_ONLY_COLLECTION}1`;
+ const key2 = `${ONYX_KEYS.COLLECTION.RAM_ONLY_COLLECTION}2`;
await Onyx.setCollection(ONYX_KEYS.COLLECTION.RAM_ONLY_COLLECTION, {
[key1]: 'test1',
[key2]: 'test2',
- })
+ });
- expect(await StorageMock.getItem(key1)).toBeNull()
- expect(await StorageMock.getItem(key2)).toBeNull()
- })
+ expect(await StorageMock.getItem(key1)).toBeNull();
+ expect(await StorageMock.getItem(key2)).toBeNull();
+ });
});
describe('skippable collection member ids', () => {
From 61b21fb844ed0a2fa347818ff15360fca483f0e8 Mon Sep 17 00:00:00 2001
From: Julian Kobrynski
Date: Mon, 2 Feb 2026 09:43:46 +0100
Subject: [PATCH 17/29] address review comments
---
lib/OnyxUtils.ts | 2 +-
tests/unit/onyxTest.ts | 9 ---------
2 files changed, 1 insertion(+), 10 deletions(-)
diff --git a/lib/OnyxUtils.ts b/lib/OnyxUtils.ts
index e7b991fc..9173a43b 100644
--- a/lib/OnyxUtils.ts
+++ b/lib/OnyxUtils.ts
@@ -1405,7 +1405,7 @@ function multiSetWithRetry(data: OnyxMultiSetInput, retryAttempt?: number): Prom
const keyValuePairsToStore = keyValuePairsToSet.filter((keyValuePair) => {
const [key] = keyValuePair;
// Filter out the RAM-only key value pairs, as they should not be saved to storage
- return !isRamOnlyKey(keyValuePair[0]) && !isRamOnlyCollectionMember(key);
+ return !isRamOnlyKey(key) && !isRamOnlyCollectionMember(key);
});
return Storage.multiSet(keyValuePairsToStore)
diff --git a/tests/unit/onyxTest.ts b/tests/unit/onyxTest.ts
index 474beef2..7a2c4212 100644
--- a/tests/unit/onyxTest.ts
+++ b/tests/unit/onyxTest.ts
@@ -2355,13 +2355,6 @@ describe('Onyx', () => {
});
it('should not save a RAM-only collection to storage', async () => {
- const entry1 = 'test 1';
-
- const entry2 = 'test 2';
-
- await Onyx.multiSet({[`${ONYX_KEYS.COLLECTION.RAM_ONLY_COLLECTION}1`]: entry1});
- await Onyx.multiSet({[`${ONYX_KEYS.COLLECTION.RAM_ONLY_COLLECTION}2`]: entry2});
-
const queuedUpdates: Array> = [];
queuedUpdates.push(
@@ -2392,8 +2385,6 @@ describe('Onyx', () => {
await Onyx.update(queuedUpdates);
- expect(true).toBeTruthy();
-
expect(await StorageMock.getItem(`${ONYX_KEYS.COLLECTION.RAM_ONLY_COLLECTION}1`)).toBeNull();
expect(await StorageMock.getItem(`${ONYX_KEYS.COLLECTION.RAM_ONLY_COLLECTION}2`)).toBeNull();
});
From 2edcd51d056485bfcc66abf0d606310993e37fc9 Mon Sep 17 00:00:00 2001
From: Julian Kobrynski
Date: Mon, 2 Feb 2026 13:46:22 +0100
Subject: [PATCH 18/29] apply feedback
---
API-INTERNAL.md | 5 +----
README.md | 3 +--
lib/Onyx.ts | 2 +-
lib/OnyxMerge/index.native.ts | 2 +-
lib/OnyxMerge/index.ts | 2 +-
lib/OnyxUtils.ts | 23 +++++++----------------
lib/types.ts | 3 +--
tests/unit/onyxTest.ts | 14 ++++++++++++--
tests/unit/onyxUtilsTest.ts | 29 +++++++++++++++++++++++++++++
9 files changed, 54 insertions(+), 29 deletions(-)
diff --git a/API-INTERNAL.md b/API-INTERNAL.md
index 9762e610..4bbd44af 100644
--- a/API-INTERNAL.md
+++ b/API-INTERNAL.md
@@ -59,10 +59,7 @@ is associated with a collection of keys.
Checks if a given key is a collection member key (not just a collection key).
isRamOnlyKey(key) ⇒
-Checks if a given key is a RAM-only key.
-
-isRamOnlyCollectionMember(key) ⇒
-Checks if a given key is a member of a RAM-only collection.
+Checks if a given key is a RAM-only key or a RAM-only collection member.
splitCollectionMemberKey(key, collectionKey) ⇒
Splits a collection member key into the collection key part and the ID part.
diff --git a/README.md b/README.md
index 30f36564..06fcacb5 100644
--- a/README.md
+++ b/README.md
@@ -472,12 +472,11 @@ Onyx.init({
ramOnlyKeys: [
ONYXKEYS.RAM_ONLY_KEY_1,
ONYXKEYS.RAM_ONLY_KEY_2,
+ ONYXKEYS.COLLECTION.RAM_ONLY_KEY_2,
],
});
```
-You can achieve a similar effect using `initWithStoredValues: false` in `useOnyx`, but that feature is deprecated and will be removed in one of the future releases.
-
### Usage
The extension interface is pretty simple, on the left sidebar you can see all the updates made to the local storage, in ascending order, and on the right pane you can see the whole the current state, payload of an action and the diff between the previous state and the current state after the action was triggered.
diff --git a/lib/Onyx.ts b/lib/Onyx.ts
index 4b9af623..4d4ce017 100644
--- a/lib/Onyx.ts
+++ b/lib/Onyx.ts
@@ -376,7 +376,7 @@ function clear(keysToPreserve: OnyxKey[] = []): Promise {
const defaultKeyValuePairs = Object.entries(
Object.keys(defaultKeyStates)
- .filter((key) => !keysToPreserve.includes(key) && !OnyxUtils.isRamOnlyKey(key) && !OnyxUtils.isRamOnlyCollectionMember(key))
+ .filter((key) => !keysToPreserve.includes(key) && !OnyxUtils.isRamOnlyKey(key))
.reduce((obj: KeyValueMapping, key) => {
// eslint-disable-next-line no-param-reassign
obj[key] = defaultKeyStates[key];
diff --git a/lib/OnyxMerge/index.native.ts b/lib/OnyxMerge/index.native.ts
index 27d4416d..ec8c242e 100644
--- a/lib/OnyxMerge/index.native.ts
+++ b/lib/OnyxMerge/index.native.ts
@@ -28,7 +28,7 @@ const applyMerge: ApplyMerge = , hasChanged);
- const shouldSkipStorageOperations = !hasChanged || OnyxUtils.isRamOnlyKey(key) || OnyxUtils.isRamOnlyCollectionMember(key);
+ const shouldSkipStorageOperations = !hasChanged || OnyxUtils.isRamOnlyKey(key);
// If the value has not changed, calling Storage.setItem() would be redundant and a waste of performance, so return early instead.
// If the key is marked as RAM-only, it should not be saved nor updated in the storage.
diff --git a/lib/OnyxMerge/index.ts b/lib/OnyxMerge/index.ts
index 2ff24d97..7eac789c 100644
--- a/lib/OnyxMerge/index.ts
+++ b/lib/OnyxMerge/index.ts
@@ -20,7 +20,7 @@ const applyMerge: ApplyMerge = , hasChanged);
- const shouldSkipStorageOperations = !hasChanged || OnyxUtils.isRamOnlyKey(key) || OnyxUtils.isRamOnlyCollectionMember(key);
+ const shouldSkipStorageOperations = !hasChanged || OnyxUtils.isRamOnlyKey(key);
// If the value has not changed, calling Storage.setItem() would be redundant and a waste of performance, so return early instead.
// If the key is marked as RAM-only, it should not be saved nor updated in the storage.
diff --git a/lib/OnyxUtils.ts b/lib/OnyxUtils.ts
index 9173a43b..c604ef64 100644
--- a/lib/OnyxUtils.ts
+++ b/lib/OnyxUtils.ts
@@ -456,28 +456,20 @@ function isCollectionMember(key: OnyxKey): boolean {
}
/**
- * Checks if a given key is a RAM-only key
+ * Checks if a given key is a RAM-only key or a RAM-only collection member
* @param key - The key to check
- * @returns true if key is a RAM-only key
+ * @returns true if key is a RAM-only key or a RAM-only collection member
*/
function isRamOnlyKey(key: OnyxKey): boolean {
- return cache.isRamOnlyKey(key);
-}
-
-/**
- * Checks if a given key is a member of a RAM-only collection
- * @param key - The key to check
- * @returns true if key is a member of RAM-only collection
- */
-function isRamOnlyCollectionMember(key: OnyxKey): boolean {
try {
const collectionKey = getCollectionKey(key);
// If collectionKey exists for a given key, check if it's a RAM-only key
- return isRamOnlyKey(collectionKey);
+ return cache.isRamOnlyKey(collectionKey);
} catch {
// If getCollectionKey throws, the key is not a collection member
- return false;
}
+
+ return cache.isRamOnlyKey(key);
}
/**
@@ -1347,7 +1339,7 @@ function setWithRetry({key, value, options}: SetParams {
const [key] = keyValuePair;
// Filter out the RAM-only key value pairs, as they should not be saved to storage
- return !isRamOnlyKey(key) && !isRamOnlyCollectionMember(key);
+ return !isRamOnlyKey(key);
});
return Storage.multiSet(keyValuePairsToStore)
@@ -1767,7 +1759,6 @@ const OnyxUtils = {
multiSetWithRetry,
setCollectionWithRetry,
isRamOnlyKey,
- isRamOnlyCollectionMember,
};
GlobalSettings.addGlobalSettingsChangeListener(({enablePerformanceMetrics}) => {
diff --git a/lib/types.ts b/lib/types.ts
index ad421c3b..5fe5f918 100644
--- a/lib/types.ts
+++ b/lib/types.ts
@@ -427,8 +427,7 @@ type InitOptions = {
skippableCollectionMemberIDs?: string[];
/**
- * This is an array of keys that when provided to Onyx are flagged as RAM-only keys, that are not supposed to be saved to disk.
- * This functionality replaces initWithStoredValues parameter from the useOnyx hook.
+ * Array of keys that when provided to Onyx are flagged as RAM-only keys, and thus are not saved to disk.
*/
ramOnlyKeys?: OnyxKey[];
};
diff --git a/tests/unit/onyxTest.ts b/tests/unit/onyxTest.ts
index 7a2c4212..499621fe 100644
--- a/tests/unit/onyxTest.ts
+++ b/tests/unit/onyxTest.ts
@@ -2199,6 +2199,8 @@ describe('Onyx', () => {
[key2]: 'updated value 2',
});
+ expect(await cache.get(key1)).toEqual('updated value 1');
+ expect(await cache.get(key2)).toEqual('updated value 2');
expect(await StorageMock.getItem(key1)).toBeNull();
expect(await StorageMock.getItem(key2)).toBeNull();
});
@@ -2385,6 +2387,8 @@ describe('Onyx', () => {
await Onyx.update(queuedUpdates);
+ expect(cache.get(`${ONYX_KEYS.COLLECTION.RAM_ONLY_COLLECTION}1`)).toEqual('updated test 1');
+ expect(cache.get(`${ONYX_KEYS.COLLECTION.RAM_ONLY_COLLECTION}2`)).toEqual('updated test 2');
expect(await StorageMock.getItem(`${ONYX_KEYS.COLLECTION.RAM_ONLY_COLLECTION}1`)).toBeNull();
expect(await StorageMock.getItem(`${ONYX_KEYS.COLLECTION.RAM_ONLY_COLLECTION}2`)).toBeNull();
});
@@ -2647,6 +2651,7 @@ describe('Onyx', () => {
it('should not save a RAM-only key to storage', async () => {
await Onyx.set(ONYX_KEYS.RAM_ONLY_TEST_KEY, 'test');
+ expect(cache.get(ONYX_KEYS.RAM_ONLY_TEST_KEY)).toEqual('test');
expect(await StorageMock.getItem(ONYX_KEYS.RAM_ONLY_TEST_KEY)).toBeNull();
});
@@ -2654,6 +2659,7 @@ describe('Onyx', () => {
const collectionMemberKey = `${ONYX_KEYS.COLLECTION.RAM_ONLY_COLLECTION}1`;
await Onyx.set(collectionMemberKey, 'test');
+ expect(cache.get(collectionMemberKey)).toEqual('test');
expect(await StorageMock.getItem(collectionMemberKey)).toBeNull();
});
});
@@ -2665,12 +2671,14 @@ describe('Onyx', () => {
await Onyx.multiSet({
[ONYX_KEYS.OTHER_TEST]: otherTestValue,
- [ONYX_KEYS.RAM_ONLY_TEST_KEY]: 'test value',
- [collectionMemberKey]: 'test value',
+ [ONYX_KEYS.RAM_ONLY_TEST_KEY]: 'test value 1',
+ [collectionMemberKey]: 'test value 2',
});
expect(await StorageMock.getItem(ONYX_KEYS.OTHER_TEST)).toEqual(otherTestValue);
+ expect(cache.get(ONYX_KEYS.RAM_ONLY_TEST_KEY)).toEqual('test value 1');
expect(await StorageMock.getItem(ONYX_KEYS.RAM_ONLY_TEST_KEY)).toBeNull();
+ expect(cache.get(collectionMemberKey)).toEqual('test value 2');
expect(await StorageMock.getItem(collectionMemberKey)).toBeNull();
});
});
@@ -2798,6 +2806,8 @@ describe('Onyx', () => {
[key2]: 'test2',
});
+ expect(cache.get(key1)).toEqual('test1');
+ expect(cache.get(key2)).toEqual('test2');
expect(await StorageMock.getItem(key1)).toBeNull();
expect(await StorageMock.getItem(key2)).toBeNull();
});
diff --git a/tests/unit/onyxUtilsTest.ts b/tests/unit/onyxUtilsTest.ts
index 36e1dd0e..3448c6ad 100644
--- a/tests/unit/onyxUtilsTest.ts
+++ b/tests/unit/onyxUtilsTest.ts
@@ -74,11 +74,14 @@ const ONYXKEYS = {
TEST_LEVEL_KEY: 'test_level_',
TEST_LEVEL_LAST_KEY: 'test_level_last_',
ROUTES: 'routes_',
+ RAM_ONLY_COLLECTION: 'ramOnlyCollection_',
},
+ RAM_ONLY_KEY: 'ramOnlyKey',
};
Onyx.init({
keys: ONYXKEYS,
+ ramOnlyKeys: [ONYXKEYS.RAM_ONLY_KEY, ONYXKEYS.COLLECTION.RAM_ONLY_COLLECTION],
});
beforeEach(() => Onyx.clear());
@@ -487,4 +490,30 @@ describe('OnyxUtils', () => {
expect(retryOperationSpy).toHaveBeenCalledTimes(1);
});
});
+
+ describe('isRamOnlyKey', () => {
+ it('should return true for RAM-only key', () => {
+ expect(OnyxUtils.isRamOnlyKey(ONYXKEYS.RAM_ONLY_KEY)).toBeTruthy();
+ });
+
+ it('should return true for RAM-only collection', () => {
+ expect(OnyxUtils.isRamOnlyKey(ONYXKEYS.COLLECTION.RAM_ONLY_COLLECTION)).toBeTruthy();
+ });
+
+ it('should return true for RAM-only collection member', () => {
+ expect(OnyxUtils.isRamOnlyKey(`${ONYXKEYS.COLLECTION.RAM_ONLY_COLLECTION}1`)).toBeTruthy();
+ });
+
+ it('should return false for a normal key', () => {
+ expect(OnyxUtils.isRamOnlyKey(ONYXKEYS.TEST_KEY)).toBeFalsy();
+ });
+
+ it('should return false for normal collection', () => {
+ expect(OnyxUtils.isRamOnlyKey(ONYXKEYS.COLLECTION.TEST_KEY)).toBeFalsy();
+ });
+
+ it('should return false for normal collection member', () => {
+ expect(OnyxUtils.isRamOnlyKey(`${ONYXKEYS.COLLECTION.TEST_KEY}1`)).toBeFalsy();
+ });
+ });
});
From 2824d573bdba389e9488bc72fc774f7cb6ca1f26 Mon Sep 17 00:00:00 2001
From: Julian Kobrynski
Date: Tue, 3 Feb 2026 09:30:14 +0100
Subject: [PATCH 19/29] clean up pre-existing RAM-only keys from storage
---
lib/Onyx.ts | 10 ++++++
tests/unit/removePreExistingKeysTest.ts | 45 +++++++++++++++++++++++++
2 files changed, 55 insertions(+)
create mode 100644 tests/unit/removePreExistingKeysTest.ts
diff --git a/lib/Onyx.ts b/lib/Onyx.ts
index 4d4ce017..843762e3 100644
--- a/lib/Onyx.ts
+++ b/lib/Onyx.ts
@@ -56,6 +56,16 @@ function init({
cache.setRamOnlyKeys(new Set(ramOnlyKeys));
+ // Clean up any pre-existing RAM-only keys from storage
+ if (ramOnlyKeys.length > 0) {
+ Storage.getAllKeys().then((storedKeys) => {
+ const keysToRemove = Array.from(storedKeys).filter((key) => OnyxUtils.isRamOnlyKey(key));
+ if (keysToRemove.length > 0) {
+ Storage.removeItems(keysToRemove);
+ }
+ });
+ }
+
if (shouldSyncMultipleInstances) {
Storage.keepInstancesSync?.((key, value) => {
cache.set(key, value);
diff --git a/tests/unit/removePreExistingKeysTest.ts b/tests/unit/removePreExistingKeysTest.ts
new file mode 100644
index 00000000..d6847a8f
--- /dev/null
+++ b/tests/unit/removePreExistingKeysTest.ts
@@ -0,0 +1,45 @@
+import Onyx from '../../lib';
+import waitForPromisesToResolve from '../utils/waitForPromisesToResolve';
+import StorageMock from '../../lib/storage';
+
+const ONYX_KEYS = {
+ TEST_KEY: 'test',
+ COLLECTION: {
+ TEST_KEY: 'test_',
+ RAM_ONLY_COLLECTION: 'ramOnlyCollection_',
+ },
+ RAM_ONLY_TEST_KEY: 'ramOnlyKey',
+};
+
+function initOnyx() {
+ Onyx.init({
+ keys: ONYX_KEYS,
+ ramOnlyKeys: [ONYX_KEYS.RAM_ONLY_TEST_KEY, ONYX_KEYS.COLLECTION.RAM_ONLY_COLLECTION],
+ });
+
+ // Onyx init introduces some side effects e.g. calls the getAllKeys
+ // We're clearing mocks to have a fresh calls history
+ return waitForPromisesToResolve().then(() => jest.clearAllMocks());
+}
+
+describe('pre-existing keys', () => {
+ it('should be removed from storage when migrated to RAM-only', async () => {
+ // Simulate a scenario where keys are migrated from non RAM-only to RAM-only
+ // Save key values to storage
+ await StorageMock.multiSet([
+ [`${ONYX_KEYS.RAM_ONLY_TEST_KEY}`, 'test value 1'],
+ [`${ONYX_KEYS.COLLECTION.RAM_ONLY_COLLECTION}entry1`, 'test value 2'],
+ ]);
+
+ // Make sure values are stored
+ expect(await StorageMock.getItem(ONYX_KEYS.RAM_ONLY_TEST_KEY)).toEqual('test value 1');
+ expect(await StorageMock.getItem(`${ONYX_KEYS.COLLECTION.RAM_ONLY_COLLECTION}entry1`)).toEqual('test value 2');
+
+ // Initialize Onyx with the ramOnlyKeys property
+ await initOnyx();
+
+ // Verify if the newly migrated RAM-only keys were removed from storage
+ expect(await StorageMock.getItem(ONYX_KEYS.RAM_ONLY_TEST_KEY)).toBeNull();
+ expect(await StorageMock.getItem(`${ONYX_KEYS.COLLECTION.RAM_ONLY_COLLECTION}entry1`)).toBeNull();
+ });
+});
From c07c7a2ec349dc5043856c8583d84b10e0eea536 Mon Sep 17 00:00:00 2001
From: Julian Kobrynski
Date: Tue, 3 Feb 2026 09:38:28 +0100
Subject: [PATCH 20/29] add missing unit tests
---
tests/unit/onyxTest.ts | 29 +++++++++++++++++++++++++++++
1 file changed, 29 insertions(+)
diff --git a/tests/unit/onyxTest.ts b/tests/unit/onyxTest.ts
index 499621fe..607b24b1 100644
--- a/tests/unit/onyxTest.ts
+++ b/tests/unit/onyxTest.ts
@@ -2621,6 +2621,21 @@ describe('Onyx', () => {
});
});
});
+
+ it('should not save a RAM-only key to storage when using merge', async () => {
+ await Onyx.merge(ONYX_KEYS.RAM_ONLY_TEST_KEY, {someProperty: 'value'});
+
+ expect(cache.get(ONYX_KEYS.RAM_ONLY_TEST_KEY)).toEqual({someProperty: 'value'});
+ expect(await StorageMock.getItem(ONYX_KEYS.RAM_ONLY_TEST_KEY)).toBeNull();
+ });
+
+ it('should not save a RAM-only collection member to storage when using merge', async () => {
+ const collectionMemberKey = `${ONYX_KEYS.COLLECTION.RAM_ONLY_COLLECTION}1`;
+ await Onyx.merge(collectionMemberKey, {data: 'test'});
+
+ expect(cache.get(collectionMemberKey)).toEqual({data: 'test'});
+ expect(await StorageMock.getItem(collectionMemberKey)).toBeNull();
+ });
});
describe('set', () => {
@@ -2941,4 +2956,18 @@ describe('Onyx', () => {
jest.restoreAllMocks();
});
});
+
+ describe('clear', () => {
+ it('should handle RAM-only keys with defaults correctly during clear', async () => {
+ // Set a value for RAM-only key
+ await Onyx.set(ONYX_KEYS.RAM_ONLY_TEST_KEY, 'some value');
+
+ await Onyx.clear();
+
+ // Verify it's not in storage
+ expect(await StorageMock.getItem(ONYX_KEYS.RAM_ONLY_TEST_KEY)).toBeNull();
+ // Verify cache state based on whether there's a default
+ expect(cache.get(ONYX_KEYS.RAM_ONLY_TEST_KEY)).toBeUndefined();
+ });
+ });
});
From eea4af1d6c632cfd85d07328301d793b103ef6d3 Mon Sep 17 00:00:00 2001
From: Julian Kobrynski
Date: Tue, 3 Feb 2026 09:40:55 +0100
Subject: [PATCH 21/29] add a missing test case for a RAM-only key with default
value
---
tests/unit/onyxTest.ts | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/tests/unit/onyxTest.ts b/tests/unit/onyxTest.ts
index 607b24b1..3f2ebf4d 100644
--- a/tests/unit/onyxTest.ts
+++ b/tests/unit/onyxTest.ts
@@ -27,6 +27,7 @@ const ONYX_KEYS = {
RAM_ONLY_COLLECTION: 'ramOnlyCollection_',
},
RAM_ONLY_TEST_KEY: 'ramOnlyKey',
+ RAM_ONLY_WITH_INITIAL_VALUE: 'ramOnlyWithInitialValue',
};
Onyx.init({
@@ -34,8 +35,9 @@ Onyx.init({
initialKeyStates: {
[ONYX_KEYS.OTHER_TEST]: 42,
[ONYX_KEYS.KEY_WITH_UNDERSCORE]: 'default',
+ [ONYX_KEYS.RAM_ONLY_WITH_INITIAL_VALUE]: 'default',
},
- ramOnlyKeys: [ONYX_KEYS.RAM_ONLY_TEST_KEY, ONYX_KEYS.COLLECTION.RAM_ONLY_COLLECTION],
+ ramOnlyKeys: [ONYX_KEYS.RAM_ONLY_TEST_KEY, ONYX_KEYS.COLLECTION.RAM_ONLY_COLLECTION, ONYX_KEYS.RAM_ONLY_WITH_INITIAL_VALUE],
skippableCollectionMemberIDs: ['skippable-id'],
});
@@ -2961,13 +2963,16 @@ describe('Onyx', () => {
it('should handle RAM-only keys with defaults correctly during clear', async () => {
// Set a value for RAM-only key
await Onyx.set(ONYX_KEYS.RAM_ONLY_TEST_KEY, 'some value');
+ await Onyx.set(ONYX_KEYS.RAM_ONLY_WITH_INITIAL_VALUE, 'some other value');
await Onyx.clear();
// Verify it's not in storage
expect(await StorageMock.getItem(ONYX_KEYS.RAM_ONLY_TEST_KEY)).toBeNull();
+ expect(await StorageMock.getItem(ONYX_KEYS.RAM_ONLY_WITH_INITIAL_VALUE)).toBeNull();
// Verify cache state based on whether there's a default
expect(cache.get(ONYX_KEYS.RAM_ONLY_TEST_KEY)).toBeUndefined();
+ expect(cache.get(ONYX_KEYS.RAM_ONLY_WITH_INITIAL_VALUE)).toEqual('default');
});
});
});
From ab32044e92f082bd5865957672b9e1f84ab62c20 Mon Sep 17 00:00:00 2001
From: Julian Kobrynski
Date: Tue, 3 Feb 2026 09:48:58 +0100
Subject: [PATCH 22/29] update readme
---
README.md | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/README.md b/README.md
index 06fcacb5..e5384e8d 100644
--- a/README.md
+++ b/README.md
@@ -462,7 +462,7 @@ Onyx.init({
### Using RAM-only keys
-You can choose not to save certain keys on disk and keep them RAM-only, that way their values will reset with each session. It also works for collections, you just have to pass an array of `ramOnlyKeys` to the `Onyx.init` method.
+You can choose not to save certain keys on disk and keep them RAM-only, that way their values will reset with each session. You just have to pass an array of `ramOnlyKeys` to the `Onyx.init` method. You can mark entire collections as RAM-only by including the collection key (e.g., `ONYXKEYS.COLLECTION.TEMP_DATA`). This will make all members of that collection RAM-only. Individual collection member keys cannot be selectively marked as RAM-only.
```javascript
import Onyx from 'react-native-onyx';
@@ -472,11 +472,13 @@ Onyx.init({
ramOnlyKeys: [
ONYXKEYS.RAM_ONLY_KEY_1,
ONYXKEYS.RAM_ONLY_KEY_2,
- ONYXKEYS.COLLECTION.RAM_ONLY_KEY_2,
+ ONYXKEYS.COLLECTION.TEMP_DATA,
],
});
```
+> Note: RAM-only keys still consume memory and will remain in cache until explicitly cleared or until Onyx.clear() is called. Use them judiciously for truly ephemeral data.
+
### Usage
The extension interface is pretty simple, on the left sidebar you can see all the updates made to the local storage, in ascending order, and on the right pane you can see the whole the current state, payload of an action and the diff between the previous state and the current state after the action was triggered.
From f62fd743afdcfc30eabe4e803bf01c750c6e1299 Mon Sep 17 00:00:00 2001
From: Julian Kobrynski
Date: Tue, 3 Feb 2026 13:05:52 +0100
Subject: [PATCH 23/29] skip storage operations for RAM-only keys in the remove
function
---
lib/OnyxUtils.ts | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/lib/OnyxUtils.ts b/lib/OnyxUtils.ts
index c604ef64..b0e2f1c1 100644
--- a/lib/OnyxUtils.ts
+++ b/lib/OnyxUtils.ts
@@ -871,6 +871,11 @@ function scheduleNotifyCollectionSubscribers(
function remove(key: TKey, isProcessingCollectionUpdate?: boolean): Promise {
cache.drop(key);
scheduleSubscriberUpdate(key, undefined as OnyxValue, undefined, isProcessingCollectionUpdate);
+
+ if (isRamOnlyKey(key)) {
+ return Promise.resolve();
+ }
+
return Storage.removeItem(key).then(() => undefined);
}
From b69c2145ecc80c39122061da98919f11a0f911d2 Mon Sep 17 00:00:00 2001
From: Julian Kobrynski
Date: Tue, 3 Feb 2026 16:05:53 +0100
Subject: [PATCH 24/29] update isRamOnlyKey comments
---
lib/OnyxUtils.ts | 16 ++++++++++++++--
1 file changed, 14 insertions(+), 2 deletions(-)
diff --git a/lib/OnyxUtils.ts b/lib/OnyxUtils.ts
index b0e2f1c1..4bf6ff63 100644
--- a/lib/OnyxUtils.ts
+++ b/lib/OnyxUtils.ts
@@ -456,9 +456,21 @@ function isCollectionMember(key: OnyxKey): boolean {
}
/**
- * Checks if a given key is a RAM-only key or a RAM-only collection member
+ * Checks if a given key is a RAM-only key, RAM-only collection key, or a RAM-only collection member
+ *
+ * For example:
+ *
+ * For the following Onyx setup
+ *
+ * ramOnlyKeys: ["ramOnlyKey", "ramOnlyCollection_"]
+ *
+ * - `isRamOnlyKey("ramOnlyKey")` would return true
+ * - `isRamOnlyKey("ramOnlyCollection_")` would return true
+ * - `isRamOnlyKey("ramOnlyCollection_1")` would return true
+ * - `isRamOnlyKey("someOtherKey")` would return false
+ *
* @param key - The key to check
- * @returns true if key is a RAM-only key or a RAM-only collection member
+ * @returns true if key is a RAM-only key, RAM-only collection key, or a RAM-only collection member
*/
function isRamOnlyKey(key: OnyxKey): boolean {
try {
From 2b78c259e2abcdddb67c66c06ee408fb3be9d6a5 Mon Sep 17 00:00:00 2001
From: Julian Kobrynski
Date: Wed, 4 Feb 2026 09:49:23 +0100
Subject: [PATCH 25/29] run automated documentation script
---
API-INTERNAL.md | 34 +++++++++++++++++++++++++++++++++-
1 file changed, 33 insertions(+), 1 deletion(-)
diff --git a/API-INTERNAL.md b/API-INTERNAL.md
index 4bbd44af..a31fa613 100644
--- a/API-INTERNAL.md
+++ b/API-INTERNAL.md
@@ -59,7 +59,16 @@ is associated with a collection of keys.
Checks if a given key is a collection member key (not just a collection key).
isRamOnlyKey(key) ⇒
-Checks if a given key is a RAM-only key or a RAM-only collection member.
+Checks if a given key is a RAM-only key, RAM-only collection key, or a RAM-only collection member
+For example:
+For the following Onyx setup
+ramOnlyKeys: ["ramOnlyKey", "ramOnlyCollection_"]
+
+isRamOnlyKey("ramOnlyKey") would return true
+isRamOnlyKey("ramOnlyCollection_") would return true
+isRamOnlyKey("ramOnlyCollection_1") would return true
+isRamOnlyKey("someOtherKey") would return false
+
splitCollectionMemberKey(key, collectionKey) ⇒
Splits a collection member key into the collection key part and the ID part.
@@ -310,6 +319,29 @@ Checks if a given key is a collection member key (not just a collection key).
| --- | --- |
| key | The key to check |
+
+
+## isRamOnlyKey(key) ⇒
+Checks if a given key is a RAM-only key, RAM-only collection key, or a RAM-only collection member
+
+For example:
+
+For the following Onyx setup
+
+ramOnlyKeys: ["ramOnlyKey", "ramOnlyCollection_"]
+
+- `isRamOnlyKey("ramOnlyKey")` would return true
+- `isRamOnlyKey("ramOnlyCollection_")` would return true
+- `isRamOnlyKey("ramOnlyCollection_1")` would return true
+- `isRamOnlyKey("someOtherKey")` would return false
+
+**Kind**: global function
+**Returns**: true if key is a RAM-only key, RAM-only collection key, or a RAM-only collection member
+
+| Param | Description |
+| --- | --- |
+| key | The key to check |
+
## splitCollectionMemberKey(key, collectionKey) ⇒
From 1fde270a12c9c11ec83f46fad7aac84717a60918 Mon Sep 17 00:00:00 2001
From: Julian Kobrynski
Date: Thu, 5 Feb 2026 08:53:53 +0100
Subject: [PATCH 26/29] add RAM-only keys to OnyxUtils perf tests
---
tests/perf-test/OnyxUtils.perf-test.ts | 3 +++
1 file changed, 3 insertions(+)
diff --git a/tests/perf-test/OnyxUtils.perf-test.ts b/tests/perf-test/OnyxUtils.perf-test.ts
index 87e332b8..01c63b1f 100644
--- a/tests/perf-test/OnyxUtils.perf-test.ts
+++ b/tests/perf-test/OnyxUtils.perf-test.ts
@@ -14,6 +14,7 @@ import type {OnyxEntry, OnyxInputKeyValueMapping, OnyxKey, RetriableOnyxOperatio
const ONYXKEYS = {
TEST_KEY: 'test',
TEST_KEY_2: 'test2',
+ RAM_ONLY_TEST_KEY: 'ramOnlyTestKey',
COLLECTION: {
TEST_KEY: 'test_',
TEST_NESTED_KEY: 'test_nested_',
@@ -24,6 +25,7 @@ const ONYXKEYS = {
TEST_KEY_5: 'test5_',
EVICTABLE_TEST_KEY: 'evictable_test_',
SNAPSHOT: 'snapshot_',
+ RAM_ONLY_TEST_COLLECTION: 'ramOnlyTestCollection_',
},
};
@@ -54,6 +56,7 @@ describe('OnyxUtils', () => {
evictableKeys,
initialKeyStates,
skippableCollectionMemberIDs: ['skippable-id'],
+ ramOnlyKeys: [ONYXKEYS.RAM_ONLY_TEST_KEY, ONYXKEYS.COLLECTION.RAM_ONLY_TEST_COLLECTION],
});
});
From bead3d3c0d0ebcfe4eaab8ce6c04b72c2a510ba4 Mon Sep 17 00:00:00 2001
From: Julian Kobrynski
Date: Thu, 5 Feb 2026 08:57:22 +0100
Subject: [PATCH 27/29] remove logic that removes pre-existing RAM-only keys
---
lib/Onyx.ts | 10 ------
tests/unit/removePreExistingKeysTest.ts | 45 -------------------------
2 files changed, 55 deletions(-)
delete mode 100644 tests/unit/removePreExistingKeysTest.ts
diff --git a/lib/Onyx.ts b/lib/Onyx.ts
index f5f85507..9bd8b5c4 100644
--- a/lib/Onyx.ts
+++ b/lib/Onyx.ts
@@ -57,16 +57,6 @@ function init({
cache.setRamOnlyKeys(new Set(ramOnlyKeys));
- // Clean up any pre-existing RAM-only keys from storage
- if (ramOnlyKeys.length > 0) {
- Storage.getAllKeys().then((storedKeys) => {
- const keysToRemove = Array.from(storedKeys).filter((key) => OnyxUtils.isRamOnlyKey(key));
- if (keysToRemove.length > 0) {
- Storage.removeItems(keysToRemove);
- }
- });
- }
-
if (shouldSyncMultipleInstances) {
Storage.keepInstancesSync?.((key, value) => {
cache.set(key, value);
diff --git a/tests/unit/removePreExistingKeysTest.ts b/tests/unit/removePreExistingKeysTest.ts
deleted file mode 100644
index d6847a8f..00000000
--- a/tests/unit/removePreExistingKeysTest.ts
+++ /dev/null
@@ -1,45 +0,0 @@
-import Onyx from '../../lib';
-import waitForPromisesToResolve from '../utils/waitForPromisesToResolve';
-import StorageMock from '../../lib/storage';
-
-const ONYX_KEYS = {
- TEST_KEY: 'test',
- COLLECTION: {
- TEST_KEY: 'test_',
- RAM_ONLY_COLLECTION: 'ramOnlyCollection_',
- },
- RAM_ONLY_TEST_KEY: 'ramOnlyKey',
-};
-
-function initOnyx() {
- Onyx.init({
- keys: ONYX_KEYS,
- ramOnlyKeys: [ONYX_KEYS.RAM_ONLY_TEST_KEY, ONYX_KEYS.COLLECTION.RAM_ONLY_COLLECTION],
- });
-
- // Onyx init introduces some side effects e.g. calls the getAllKeys
- // We're clearing mocks to have a fresh calls history
- return waitForPromisesToResolve().then(() => jest.clearAllMocks());
-}
-
-describe('pre-existing keys', () => {
- it('should be removed from storage when migrated to RAM-only', async () => {
- // Simulate a scenario where keys are migrated from non RAM-only to RAM-only
- // Save key values to storage
- await StorageMock.multiSet([
- [`${ONYX_KEYS.RAM_ONLY_TEST_KEY}`, 'test value 1'],
- [`${ONYX_KEYS.COLLECTION.RAM_ONLY_COLLECTION}entry1`, 'test value 2'],
- ]);
-
- // Make sure values are stored
- expect(await StorageMock.getItem(ONYX_KEYS.RAM_ONLY_TEST_KEY)).toEqual('test value 1');
- expect(await StorageMock.getItem(`${ONYX_KEYS.COLLECTION.RAM_ONLY_COLLECTION}entry1`)).toEqual('test value 2');
-
- // Initialize Onyx with the ramOnlyKeys property
- await initOnyx();
-
- // Verify if the newly migrated RAM-only keys were removed from storage
- expect(await StorageMock.getItem(ONYX_KEYS.RAM_ONLY_TEST_KEY)).toBeNull();
- expect(await StorageMock.getItem(`${ONYX_KEYS.COLLECTION.RAM_ONLY_COLLECTION}entry1`)).toBeNull();
- });
-});
From 0848187f93a5c1db96a6bd0267628cefc16af8ad Mon Sep 17 00:00:00 2001
From: Julian Kobrynski
Date: Thu, 5 Feb 2026 09:39:25 +0100
Subject: [PATCH 28/29] add explaining comment
---
lib/Onyx.ts | 1 +
1 file changed, 1 insertion(+)
diff --git a/lib/Onyx.ts b/lib/Onyx.ts
index 9bd8b5c4..bdac8c89 100644
--- a/lib/Onyx.ts
+++ b/lib/Onyx.ts
@@ -381,6 +381,7 @@ function clear(keysToPreserve: OnyxKey[] = []): Promise {
updatePromises.push(OnyxUtils.scheduleNotifyCollectionSubscribers(key, value.newValues, value.oldValues));
}
+ // Exclude RAM-only keys to prevent them from being saved to storage
const defaultKeyValuePairs = Object.entries(
Object.keys(defaultKeyStates)
.filter((key) => !keysToPreserve.includes(key) && !OnyxUtils.isRamOnlyKey(key))
From 94ece5a4ebd8dc752c6606ae7ca3ba0d283fa8e7 Mon Sep 17 00:00:00 2001
From: Julian Kobrynski
Date: Thu, 5 Feb 2026 13:32:05 +0100
Subject: [PATCH 29/29] add RAM-only keys to perf tests
---
tests/perf-test/OnyxConnectionManager.perf-test.ts | 3 +++
tests/perf-test/OnyxUtils.perf-test.ts | 14 ++++++++++++++
tests/perf-test/useOnyx.perf-test.tsx | 2 ++
3 files changed, 19 insertions(+)
diff --git a/tests/perf-test/OnyxConnectionManager.perf-test.ts b/tests/perf-test/OnyxConnectionManager.perf-test.ts
index 19ac5320..284b4d0c 100644
--- a/tests/perf-test/OnyxConnectionManager.perf-test.ts
+++ b/tests/perf-test/OnyxConnectionManager.perf-test.ts
@@ -8,6 +8,7 @@ import {getRandomReportActions} from '../utils/collections/reportActions';
const ONYXKEYS = {
TEST_KEY: 'test',
TEST_KEY_2: 'test2',
+ RAM_ONLY_TEST_KEY: 'ramOnlyTestKey',
COLLECTION: {
TEST_KEY: 'test_',
TEST_NESTED_KEY: 'test_nested_',
@@ -18,6 +19,7 @@ const ONYXKEYS = {
TEST_KEY_5: 'test5_',
EVICTABLE_TEST_KEY: 'evictable_test_',
SNAPSHOT: 'snapshot_',
+ RAM_ONLY_TEST_COLLECTION: 'ramOnlyTestCollection_',
},
};
@@ -47,6 +49,7 @@ describe('OnyxConnectionManager', () => {
maxCachedKeysCount: 100000,
evictableKeys: [ONYXKEYS.COLLECTION.EVICTABLE_TEST_KEY],
skippableCollectionMemberIDs: ['skippable-id'],
+ ramOnlyKeys: [ONYXKEYS.RAM_ONLY_TEST_KEY, ONYXKEYS.COLLECTION.RAM_ONLY_TEST_COLLECTION],
});
});
diff --git a/tests/perf-test/OnyxUtils.perf-test.ts b/tests/perf-test/OnyxUtils.perf-test.ts
index 01c63b1f..5a00d910 100644
--- a/tests/perf-test/OnyxUtils.perf-test.ts
+++ b/tests/perf-test/OnyxUtils.perf-test.ts
@@ -147,6 +147,20 @@ describe('OnyxUtils', () => {
});
});
+ describe('isRamOnlyKey', () => {
+ test('one call for RAM-only key', async () => {
+ await measureFunction(() => OnyxUtils.isRamOnlyKey(ONYXKEYS.RAM_ONLY_TEST_KEY));
+ });
+
+ test('one call for RAM-only collection key', async () => {
+ await measureFunction(() => OnyxUtils.isRamOnlyKey(ONYXKEYS.COLLECTION.RAM_ONLY_TEST_COLLECTION));
+ });
+
+ test('one call for RAM-only collection member key', async () => {
+ await measureFunction(() => OnyxUtils.isRamOnlyKey(`${ONYXKEYS.COLLECTION.RAM_ONLY_TEST_COLLECTION}1`));
+ });
+ });
+
describe('isCollectionMemberKey', () => {
test('one call with correct key', async () => {
await measureFunction(() => OnyxUtils.isCollectionMemberKey(collectionKey, `${collectionKey}entry1`));
diff --git a/tests/perf-test/useOnyx.perf-test.tsx b/tests/perf-test/useOnyx.perf-test.tsx
index 78672203..963d5832 100644
--- a/tests/perf-test/useOnyx.perf-test.tsx
+++ b/tests/perf-test/useOnyx.perf-test.tsx
@@ -11,6 +11,7 @@ const ONYXKEYS = {
TEST_KEY: 'test',
TEST_KEY_2: 'test2',
TEST_KEY_3: 'test3',
+ RAM_ONLY_TEST_KEY: 'ramOnlyTestKey',
};
const dataMatcher = (onyxKey: OnyxKey, expected: unknown) => `data: ${onyxKey}_${JSON.stringify(expected)}`;
@@ -57,6 +58,7 @@ describe('useOnyx', () => {
Onyx.init({
keys: ONYXKEYS,
maxCachedKeysCount: 100000,
+ ramOnlyKeys: [ONYXKEYS.RAM_ONLY_TEST_KEY],
});
});