react-native-onyx 2.0.77 → 2.0.78
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/Onyx.js +4 -2
- package/dist/OnyxCache.d.ts +12 -3
- package/dist/OnyxCache.js +8 -0
- package/dist/OnyxConnectionManager.d.ts +18 -0
- package/dist/OnyxConnectionManager.js +11 -2
- package/dist/OnyxUtils.js +6 -7
- package/dist/useOnyx.d.ts +5 -0
- package/dist/useOnyx.js +34 -7
- package/package.json +1 -1
package/dist/Onyx.js
CHANGED
|
@@ -30,7 +30,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
30
30
|
const underscore_1 = __importDefault(require("underscore"));
|
|
31
31
|
const pick_1 = __importDefault(require("lodash/pick"));
|
|
32
32
|
const Logger = __importStar(require("./Logger"));
|
|
33
|
-
const OnyxCache_1 =
|
|
33
|
+
const OnyxCache_1 = __importStar(require("./OnyxCache"));
|
|
34
34
|
const PerformanceUtils = __importStar(require("./PerformanceUtils"));
|
|
35
35
|
const storage_1 = __importDefault(require("./storage"));
|
|
36
36
|
const utils_1 = __importDefault(require("./utils"));
|
|
@@ -390,7 +390,7 @@ function mergeCollection(collectionKey, collection) {
|
|
|
390
390
|
function clear(keysToPreserve = []) {
|
|
391
391
|
const defaultKeyStates = OnyxUtils_1.default.getDefaultKeyStates();
|
|
392
392
|
const initialKeys = Object.keys(defaultKeyStates);
|
|
393
|
-
|
|
393
|
+
const promise = OnyxUtils_1.default.getAllKeys()
|
|
394
394
|
.then((cachedKeys) => {
|
|
395
395
|
OnyxCache_1.default.clearNullishStorageKeys();
|
|
396
396
|
const keysToBeClearedFromStorage = [];
|
|
@@ -459,6 +459,7 @@ function clear(keysToPreserve = []) {
|
|
|
459
459
|
// Remove only the items that we want cleared from storage, and reset others to default
|
|
460
460
|
keysToBeClearedFromStorage.forEach((key) => OnyxCache_1.default.drop(key));
|
|
461
461
|
return storage_1.default.removeItems(keysToBeClearedFromStorage)
|
|
462
|
+
.then(() => OnyxConnectionManager_1.default.refreshSessionID())
|
|
462
463
|
.then(() => storage_1.default.multiSet(defaultKeyValuePairs))
|
|
463
464
|
.then(() => {
|
|
464
465
|
DevTools_1.default.clearState(keysToPreserve);
|
|
@@ -466,6 +467,7 @@ function clear(keysToPreserve = []) {
|
|
|
466
467
|
});
|
|
467
468
|
})
|
|
468
469
|
.then(() => undefined);
|
|
470
|
+
return OnyxCache_1.default.captureTask(OnyxCache_1.TASK.CLEAR, promise);
|
|
469
471
|
}
|
|
470
472
|
function updateSnapshots(data) {
|
|
471
473
|
const snapshotCollectionKey = OnyxUtils_1.default.getSnapshotKey();
|
package/dist/OnyxCache.d.ts
CHANGED
|
@@ -1,4 +1,11 @@
|
|
|
1
|
+
import type { ValueOf } from 'type-fest';
|
|
1
2
|
import type { OnyxKey, OnyxValue } from './types';
|
|
3
|
+
declare const TASK: {
|
|
4
|
+
readonly GET: "get";
|
|
5
|
+
readonly GET_ALL_KEYS: "getAllKeys";
|
|
6
|
+
readonly CLEAR: "clear";
|
|
7
|
+
};
|
|
8
|
+
type CacheTask = ValueOf<typeof TASK> | `${ValueOf<typeof TASK>}:${string}`;
|
|
2
9
|
/**
|
|
3
10
|
* In memory cache providing data by reference
|
|
4
11
|
* Encapsulates Onyx cache related functionality
|
|
@@ -67,20 +74,20 @@ declare class OnyxCache {
|
|
|
67
74
|
* Check whether the given task is already running
|
|
68
75
|
* @param taskName - unique name given for the task
|
|
69
76
|
*/
|
|
70
|
-
hasPendingTask(taskName:
|
|
77
|
+
hasPendingTask(taskName: CacheTask): boolean;
|
|
71
78
|
/**
|
|
72
79
|
* Use this method to prevent concurrent calls for the same thing
|
|
73
80
|
* Instead of calling the same task again use the existing promise
|
|
74
81
|
* provided from this function
|
|
75
82
|
* @param taskName - unique name given for the task
|
|
76
83
|
*/
|
|
77
|
-
getTaskPromise(taskName:
|
|
84
|
+
getTaskPromise(taskName: CacheTask): Promise<OnyxValue<OnyxKey> | OnyxKey[]> | undefined;
|
|
78
85
|
/**
|
|
79
86
|
* Capture a promise for a given task so other caller can
|
|
80
87
|
* hook up to the promise if it's still pending
|
|
81
88
|
* @param taskName - unique name for the task
|
|
82
89
|
*/
|
|
83
|
-
captureTask(taskName:
|
|
90
|
+
captureTask(taskName: CacheTask, promise: Promise<OnyxValue<OnyxKey>>): Promise<OnyxValue<OnyxKey>>;
|
|
84
91
|
/** Adds a key to the top of the recently accessed keys */
|
|
85
92
|
addToAccessedKeys(key: OnyxKey): void;
|
|
86
93
|
/** Remove keys that don't fall into the range of recently used keys */
|
|
@@ -92,3 +99,5 @@ declare class OnyxCache {
|
|
|
92
99
|
}
|
|
93
100
|
declare const instance: OnyxCache;
|
|
94
101
|
export default instance;
|
|
102
|
+
export { TASK };
|
|
103
|
+
export type { CacheTask };
|
package/dist/OnyxCache.js
CHANGED
|
@@ -3,9 +3,17 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.TASK = void 0;
|
|
6
7
|
const fast_equals_1 = require("fast-equals");
|
|
7
8
|
const bindAll_1 = __importDefault(require("lodash/bindAll"));
|
|
8
9
|
const utils_1 = __importDefault(require("./utils"));
|
|
10
|
+
// Task constants
|
|
11
|
+
const TASK = {
|
|
12
|
+
GET: 'get',
|
|
13
|
+
GET_ALL_KEYS: 'getAllKeys',
|
|
14
|
+
CLEAR: 'clear',
|
|
15
|
+
};
|
|
16
|
+
exports.TASK = TASK;
|
|
9
17
|
/**
|
|
10
18
|
* In memory cache providing data by reference
|
|
11
19
|
* Encapsulates Onyx cache related functionality
|
|
@@ -25,6 +25,20 @@ declare class OnyxConnectionManager {
|
|
|
25
25
|
* Stores the last generated callback ID which will be incremented when making a new connection.
|
|
26
26
|
*/
|
|
27
27
|
private lastCallbackID;
|
|
28
|
+
/**
|
|
29
|
+
* Stores the last generated session ID for the connection manager. The current session ID
|
|
30
|
+
* is appended to the connection IDs and it's used to create new different connections for the same key
|
|
31
|
+
* when `refreshSessionID()` is called.
|
|
32
|
+
*
|
|
33
|
+
* When calling `Onyx.clear()` after a logout operation some connections might remain active as they
|
|
34
|
+
* aren't tied to the React's lifecycle e.g. `Onyx.connect()` usage, causing infinite loading state issues to new `useOnyx()` subscribers
|
|
35
|
+
* that are connecting to the same key as we didn't populate the cache again because we are still reusing such connections.
|
|
36
|
+
*
|
|
37
|
+
* To elimitate this problem, the session ID must be refreshed during the `Onyx.clear()` call (by using `refreshSessionID()`)
|
|
38
|
+
* in order to create fresh connections when new subscribers connect to the same keys again, allowing them
|
|
39
|
+
* to use the cache system correctly and avoid the mentioned issues in `useOnyx()`.
|
|
40
|
+
*/
|
|
41
|
+
private sessionID;
|
|
28
42
|
constructor();
|
|
29
43
|
/**
|
|
30
44
|
* Generates a connection ID based on the `connectOptions` object passed to the function.
|
|
@@ -54,6 +68,10 @@ declare class OnyxConnectionManager {
|
|
|
54
68
|
* Disconnect all subscribers from Onyx.
|
|
55
69
|
*/
|
|
56
70
|
disconnectAll(): void;
|
|
71
|
+
/**
|
|
72
|
+
* Refreshes the connection manager's session ID.
|
|
73
|
+
*/
|
|
74
|
+
refreshSessionID(): void;
|
|
57
75
|
/**
|
|
58
76
|
* Adds the connection to the eviction block list. Connections added to this list can never be evicted.
|
|
59
77
|
* */
|
|
@@ -38,8 +38,9 @@ class OnyxConnectionManager {
|
|
|
38
38
|
constructor() {
|
|
39
39
|
this.connectionsMap = new Map();
|
|
40
40
|
this.lastCallbackID = 0;
|
|
41
|
+
this.sessionID = Str.guid();
|
|
41
42
|
// Binds all public methods to prevent problems with `this`.
|
|
42
|
-
(0, bindAll_1.default)(this, 'generateConnectionID', 'fireCallbacks', 'connect', 'disconnect', 'disconnectAll', 'addToEvictionBlockList', 'removeFromEvictionBlockList');
|
|
43
|
+
(0, bindAll_1.default)(this, 'generateConnectionID', 'fireCallbacks', 'connect', 'disconnect', 'disconnectAll', 'refreshSessionID', 'addToEvictionBlockList', 'removeFromEvictionBlockList');
|
|
43
44
|
}
|
|
44
45
|
/**
|
|
45
46
|
* Generates a connection ID based on the `connectOptions` object passed to the function.
|
|
@@ -49,7 +50,9 @@ class OnyxConnectionManager {
|
|
|
49
50
|
*/
|
|
50
51
|
generateConnectionID(connectOptions) {
|
|
51
52
|
const { key, initWithStoredValues, reuseConnection, waitForCollectionCallback } = connectOptions;
|
|
52
|
-
|
|
53
|
+
// The current session ID is appended to the connection ID so we can have different connections
|
|
54
|
+
// after an `Onyx.clear()` operation.
|
|
55
|
+
let suffix = `,sessionID=${this.sessionID}`;
|
|
53
56
|
// We will generate a unique ID in any of the following situations:
|
|
54
57
|
// - `reuseConnection` is `false`. That means the subscriber explicitly wants the connection to not be reused.
|
|
55
58
|
// - `initWithStoredValues` is `false`. This flag changes the subscription flow when set to `false`, so the connection can't be reused.
|
|
@@ -162,6 +165,12 @@ class OnyxConnectionManager {
|
|
|
162
165
|
});
|
|
163
166
|
this.connectionsMap.clear();
|
|
164
167
|
}
|
|
168
|
+
/**
|
|
169
|
+
* Refreshes the connection manager's session ID.
|
|
170
|
+
*/
|
|
171
|
+
refreshSessionID() {
|
|
172
|
+
this.sessionID = Str.guid();
|
|
173
|
+
}
|
|
165
174
|
/**
|
|
166
175
|
* Adds the connection to the eviction block list. Connections added to this list can never be evicted.
|
|
167
176
|
* */
|
package/dist/OnyxUtils.js
CHANGED
|
@@ -32,7 +32,7 @@ const fast_equals_1 = require("fast-equals");
|
|
|
32
32
|
const clone_1 = __importDefault(require("lodash/clone"));
|
|
33
33
|
const DevTools_1 = __importDefault(require("./DevTools"));
|
|
34
34
|
const Logger = __importStar(require("./Logger"));
|
|
35
|
-
const OnyxCache_1 =
|
|
35
|
+
const OnyxCache_1 = __importStar(require("./OnyxCache"));
|
|
36
36
|
const PerformanceUtils = __importStar(require("./PerformanceUtils"));
|
|
37
37
|
const Str = __importStar(require("./Str"));
|
|
38
38
|
const batch_1 = __importDefault(require("./batch"));
|
|
@@ -187,7 +187,7 @@ function get(key) {
|
|
|
187
187
|
if (OnyxCache_1.default.hasCacheForKey(key)) {
|
|
188
188
|
return Promise.resolve(OnyxCache_1.default.get(key));
|
|
189
189
|
}
|
|
190
|
-
const taskName =
|
|
190
|
+
const taskName = `${OnyxCache_1.TASK.GET}:${key}`;
|
|
191
191
|
// When a value retrieving task for this key is still running hook to it
|
|
192
192
|
if (OnyxCache_1.default.hasPendingTask(taskName)) {
|
|
193
193
|
return OnyxCache_1.default.getTaskPromise(taskName);
|
|
@@ -229,7 +229,7 @@ function multiGet(keys) {
|
|
|
229
229
|
dataMap.set(key, cacheValue);
|
|
230
230
|
return;
|
|
231
231
|
}
|
|
232
|
-
const pendingKey =
|
|
232
|
+
const pendingKey = `${OnyxCache_1.TASK.GET}:${key}`;
|
|
233
233
|
if (OnyxCache_1.default.hasPendingTask(pendingKey)) {
|
|
234
234
|
pendingTasks.push(OnyxCache_1.default.getTaskPromise(pendingKey));
|
|
235
235
|
pendingKeys.push(key);
|
|
@@ -300,10 +300,9 @@ function getAllKeys() {
|
|
|
300
300
|
if (cachedKeys.size > 0) {
|
|
301
301
|
return Promise.resolve(cachedKeys);
|
|
302
302
|
}
|
|
303
|
-
const taskName = 'getAllKeys';
|
|
304
303
|
// When a value retrieving task for all keys is still running hook to it
|
|
305
|
-
if (OnyxCache_1.default.hasPendingTask(
|
|
306
|
-
return OnyxCache_1.default.getTaskPromise(
|
|
304
|
+
if (OnyxCache_1.default.hasPendingTask(OnyxCache_1.TASK.GET_ALL_KEYS)) {
|
|
305
|
+
return OnyxCache_1.default.getTaskPromise(OnyxCache_1.TASK.GET_ALL_KEYS);
|
|
307
306
|
}
|
|
308
307
|
// Otherwise retrieve the keys from storage and capture a promise to aid concurrent usages
|
|
309
308
|
const promise = storage_1.default.getAllKeys().then((keys) => {
|
|
@@ -311,7 +310,7 @@ function getAllKeys() {
|
|
|
311
310
|
// return the updated set of keys
|
|
312
311
|
return OnyxCache_1.default.getAllKeys();
|
|
313
312
|
});
|
|
314
|
-
return OnyxCache_1.default.captureTask(
|
|
313
|
+
return OnyxCache_1.default.captureTask(OnyxCache_1.TASK.GET_ALL_KEYS, promise);
|
|
315
314
|
}
|
|
316
315
|
/**
|
|
317
316
|
* Returns set of all registered collection keys
|
package/dist/useOnyx.d.ts
CHANGED
|
@@ -12,6 +12,11 @@ type BaseUseOnyxOptions = {
|
|
|
12
12
|
* If set to `true`, data will be retrieved from cache during the first render even if there is a pending merge for the key.
|
|
13
13
|
*/
|
|
14
14
|
allowStaleData?: boolean;
|
|
15
|
+
/**
|
|
16
|
+
* If set to `false`, the connection won't be reused between other subscribers that are listening to the same Onyx key
|
|
17
|
+
* with the same connect configurations.
|
|
18
|
+
*/
|
|
19
|
+
reuseConnection?: boolean;
|
|
15
20
|
};
|
|
16
21
|
type UseOnyxInitialValueOption<TInitialValue> = {
|
|
17
22
|
/**
|
package/dist/useOnyx.js
CHANGED
|
@@ -1,11 +1,34 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
2
25
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
26
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
27
|
};
|
|
5
28
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
29
|
const fast_equals_1 = require("fast-equals");
|
|
7
30
|
const react_1 = require("react");
|
|
8
|
-
const OnyxCache_1 =
|
|
31
|
+
const OnyxCache_1 = __importStar(require("./OnyxCache"));
|
|
9
32
|
const OnyxConnectionManager_1 = __importDefault(require("./OnyxConnectionManager"));
|
|
10
33
|
const OnyxUtils_1 = __importDefault(require("./OnyxUtils"));
|
|
11
34
|
const useLiveRef_1 = __importDefault(require("./useLiveRef"));
|
|
@@ -144,11 +167,14 @@ function useOnyx(key, options) {
|
|
|
144
167
|
else {
|
|
145
168
|
areValuesEqual = (0, fast_equals_1.shallowEqual)((_c = previousValueRef.current) !== null && _c !== void 0 ? _c : undefined, newValueRef.current);
|
|
146
169
|
}
|
|
147
|
-
//
|
|
148
|
-
// and the result
|
|
149
|
-
//
|
|
150
|
-
|
|
151
|
-
|
|
170
|
+
// We updated the cached value and the result in the following conditions:
|
|
171
|
+
// We will update the cached value and the result in any of the following situations:
|
|
172
|
+
// - The previously cached value is different from the new value.
|
|
173
|
+
// - The previously cached value is `null` (not set from cache yet) and we have cache for this key
|
|
174
|
+
// OR we have a pending `Onyx.clear()` task (if `Onyx.clear()` is running cache might not be available anymore
|
|
175
|
+
// so we update the cached value/result right away in order to prevent infinite loading state issues).
|
|
176
|
+
const shouldUpdateResult = !areValuesEqual || (previousValueRef.current === null && (hasCacheForKey || OnyxCache_1.default.hasPendingTask(OnyxCache_1.TASK.CLEAR)));
|
|
177
|
+
if (shouldUpdateResult) {
|
|
152
178
|
previousValueRef.current = newValueRef.current;
|
|
153
179
|
// If the new value is `null` we default it to `undefined` to ensure the consumer gets a consistent result from the hook.
|
|
154
180
|
resultRef.current = [(_d = previousValueRef.current) !== null && _d !== void 0 ? _d : undefined, { status: newFetchStatus !== null && newFetchStatus !== void 0 ? newFetchStatus : 'loaded' }];
|
|
@@ -169,6 +195,7 @@ function useOnyx(key, options) {
|
|
|
169
195
|
},
|
|
170
196
|
initWithStoredValues: options === null || options === void 0 ? void 0 : options.initWithStoredValues,
|
|
171
197
|
waitForCollectionCallback: OnyxUtils_1.default.isCollectionKey(key),
|
|
198
|
+
reuseConnection: options === null || options === void 0 ? void 0 : options.reuseConnection,
|
|
172
199
|
});
|
|
173
200
|
checkEvictableKey();
|
|
174
201
|
return () => {
|
|
@@ -178,7 +205,7 @@ function useOnyx(key, options) {
|
|
|
178
205
|
OnyxConnectionManager_1.default.disconnect(connectionRef.current);
|
|
179
206
|
isFirstConnectionRef.current = false;
|
|
180
207
|
};
|
|
181
|
-
}, [key, options === null || options === void 0 ? void 0 : options.initWithStoredValues, checkEvictableKey]);
|
|
208
|
+
}, [key, options === null || options === void 0 ? void 0 : options.initWithStoredValues, options === null || options === void 0 ? void 0 : options.reuseConnection, checkEvictableKey]);
|
|
182
209
|
(0, react_1.useEffect)(() => {
|
|
183
210
|
checkEvictableKey();
|
|
184
211
|
}, [checkEvictableKey]);
|