react-native-onyx 1.0.80 → 1.0.82
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +40 -0
- package/dist/web.development.js +55 -29
- package/dist/web.development.js.map +1 -1
- package/dist/web.min.js +1 -1
- package/dist/web.min.js.map +1 -1
- package/lib/Onyx.js +4 -21
- package/lib/fastMerge.js +3 -4
- package/lib/storage/providers/IDBKeyVal.js +2 -1
- package/lib/utils.js +23 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -137,6 +137,46 @@ export default withOnyx({
|
|
|
137
137
|
|
|
138
138
|
It is preferable to use the HOC over `Onyx.connect()` in React code as `withOnyx()` will delay the rendering of the wrapped component until all keys have been accessed and made available.
|
|
139
139
|
|
|
140
|
+
### Dependent Onyx Keys and withOnyx()
|
|
141
|
+
Some components need to subscribe to multiple Onyx keys at once and sometimes, one key might rely on the data from another key. This is similar to a JOIN in SQL.
|
|
142
|
+
|
|
143
|
+
Example: To get the policy of a report, the `policy` key depends on the `report` key.
|
|
144
|
+
|
|
145
|
+
```javascript
|
|
146
|
+
export default withOnyx({
|
|
147
|
+
report: {
|
|
148
|
+
key: ({reportID) => `${ONYXKEYS.COLLECTION.REPORT}${reportID}`,
|
|
149
|
+
},
|
|
150
|
+
policy: {
|
|
151
|
+
key: ({report}) => `${ONYXKEYS.COLLECTION.POLICY}${report.policyID}`,
|
|
152
|
+
},
|
|
153
|
+
})(App);
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
Background info:
|
|
157
|
+
- The `key` value can be a function that returns the key that Onyx subscribes to
|
|
158
|
+
- The first argument to the `key` function is the `props` from the component
|
|
159
|
+
|
|
160
|
+
**Detailed explanation of how this is handled and rendered:**
|
|
161
|
+
1. The component mounts with a `reportID={1234}` prop
|
|
162
|
+
2. `withOnyx` evaluates the mapping
|
|
163
|
+
3. `withOnyx` connects to the key `reports_1234` because of the prop passed to the component
|
|
164
|
+
3. `withOnyx` connects to the key `policies_undefined` because `report` doesn't exist in the props yet, so the `policyID` defaults to `undefined`. * (see note below)
|
|
165
|
+
4. Onyx reads the data and updates the state of `withOnyx` with:
|
|
166
|
+
- `report={{reportID: 1234, policyID: 1, ... the rest of the object ...}}`
|
|
167
|
+
- `policy={undefined}` (since there is no policy with ID `undefined`)
|
|
168
|
+
5. There is still an `undefined` key in the mapping, so Onyx reads the data again
|
|
169
|
+
6. This time `withOnyx` connects to the key `policies_1` because the `report` object exists in the component's state and it has a `policyID: 1`
|
|
170
|
+
7. Onyx reads the data and updates the state of withOnyx with:
|
|
171
|
+
- `policy={{policyID: 1, ... the rest of the object ...}`
|
|
172
|
+
8. Now all mappings have values that are defined (not undefined) and the component is rendered with all necessary data
|
|
173
|
+
|
|
174
|
+
* It is VERY important to NOT use empty string default values like `report.policyID || ''`. This results in the key returned to `withOnyx` as `policies_` which subscribes to the ENTIRE POLICY COLLECTION and is most assuredly not what you were intending. You can use a default of `0` (as long as you are reasonably sure that there is never a policyID=0). This allows Onyx to return `undefined` as the value of the policy key, which is handled by `withOnyx` appropriately.
|
|
175
|
+
|
|
176
|
+
DO NOT use more than one `withOnyx` component at a time. It adds overhead and prevents some optimizations like batched rendering from working to its full potential.
|
|
177
|
+
|
|
178
|
+
It's also beneficial to use a [selector](https://github.com/Expensify/react-native-onyx/blob/main/API.md#connectmapping--number) with the mapping in case you need to grab a single item in a collection (like a single report action).
|
|
179
|
+
|
|
140
180
|
## Collections
|
|
141
181
|
|
|
142
182
|
Collections allow keys with similar value types to be subscribed together by subscribing to the collection key. To define one, it must be included in the `ONYXKEYS.COLLECTION` object and it must be suffixed with an underscore. Member keys should use a unique identifier or index after the collection key prefix (e.g. `report_42`).
|
package/dist/web.development.js
CHANGED
|
@@ -77,9 +77,10 @@ __webpack_require__.r(__webpack_exports__);
|
|
|
77
77
|
/* harmony import */ var _OnyxCache__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./OnyxCache */ "./lib/OnyxCache.js");
|
|
78
78
|
/* harmony import */ var _Str__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./Str */ "./lib/Str.js");
|
|
79
79
|
/* harmony import */ var _createDeferredTask__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./createDeferredTask */ "./lib/createDeferredTask.js");
|
|
80
|
-
/* harmony import */ var
|
|
80
|
+
/* harmony import */ var _fastMerge__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ./fastMerge */ "./lib/fastMerge.js");
|
|
81
81
|
/* harmony import */ var _metrics_PerformanceUtils__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./metrics/PerformanceUtils */ "./lib/metrics/PerformanceUtils.js");
|
|
82
82
|
/* harmony import */ var _storage__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./storage */ "./lib/storage/index.web.js");
|
|
83
|
+
/* harmony import */ var _utils__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ./utils */ "./lib/utils.js");
|
|
83
84
|
/* harmony import */ var _batch__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./batch */ "./lib/batch.js");
|
|
84
85
|
/* eslint-disable no-continue */
|
|
85
86
|
|
|
@@ -93,6 +94,7 @@ __webpack_require__.r(__webpack_exports__);
|
|
|
93
94
|
|
|
94
95
|
|
|
95
96
|
|
|
97
|
+
|
|
96
98
|
// Method constants
|
|
97
99
|
const METHOD = {
|
|
98
100
|
SET: 'set',
|
|
@@ -1073,24 +1075,6 @@ function hasPendingMergeForKey(key) {
|
|
|
1073
1075
|
return Boolean(mergeQueue[key]);
|
|
1074
1076
|
}
|
|
1075
1077
|
|
|
1076
|
-
/**
|
|
1077
|
-
* We generally want to remove top-level nullish values from objects written to disk and cache, because it decreases the amount of data stored in memory and on disk.
|
|
1078
|
-
* On native, when merging an existing value with new changes, SQLite will use JSON_PATCH, which removes top-level nullish values.
|
|
1079
|
-
* To be consistent with the behaviour for merge, we'll also want to remove nullish values for "set" operations.
|
|
1080
|
-
* On web, IndexedDB will keep the top-level keys along with a null value and this uses up storage and memory.
|
|
1081
|
-
* This method will ensure that keys for null values are removed before an object is written to disk and cache so that all platforms are storing the data in the same efficient way.
|
|
1082
|
-
* @private
|
|
1083
|
-
* @param {*} value
|
|
1084
|
-
* @returns {*}
|
|
1085
|
-
*/
|
|
1086
|
-
function removeNullObjectValues(value) {
|
|
1087
|
-
if (underscore__WEBPACK_IMPORTED_MODULE_1___default().isArray(value) || !underscore__WEBPACK_IMPORTED_MODULE_1___default().isObject(value)) {
|
|
1088
|
-
return value;
|
|
1089
|
-
}
|
|
1090
|
-
|
|
1091
|
-
return underscore__WEBPACK_IMPORTED_MODULE_1___default().omit(value, (objectValue) => underscore__WEBPACK_IMPORTED_MODULE_1___default().isNull(objectValue));
|
|
1092
|
-
}
|
|
1093
|
-
|
|
1094
1078
|
/**
|
|
1095
1079
|
* Write a value to our store with the given key
|
|
1096
1080
|
*
|
|
@@ -1108,7 +1092,7 @@ function set(key, value) {
|
|
|
1108
1092
|
_Logger__WEBPACK_IMPORTED_MODULE_5__.logAlert(`Onyx.set() called after Onyx.merge() for key: ${key}. It is recommended to use set() or merge() not both.`);
|
|
1109
1093
|
}
|
|
1110
1094
|
|
|
1111
|
-
const valueWithNullRemoved = removeNullObjectValues(value);
|
|
1095
|
+
const valueWithNullRemoved = _utils__WEBPACK_IMPORTED_MODULE_9__["default"].removeNullObjectValues(value);
|
|
1112
1096
|
|
|
1113
1097
|
const hasChanged = _OnyxCache__WEBPACK_IMPORTED_MODULE_3__["default"].hasValueChanged(key, valueWithNullRemoved);
|
|
1114
1098
|
|
|
@@ -1178,7 +1162,7 @@ function applyMerge(existingValue, changes) {
|
|
|
1178
1162
|
// Object values are merged one after the other
|
|
1179
1163
|
// lodash adds a small overhead so we don't use it here
|
|
1180
1164
|
// eslint-disable-next-line prefer-object-spread, rulesdir/prefer-underscore-method
|
|
1181
|
-
return underscore__WEBPACK_IMPORTED_MODULE_1___default().reduce(changes, (modifiedData, change) => (0,
|
|
1165
|
+
return underscore__WEBPACK_IMPORTED_MODULE_1___default().reduce(changes, (modifiedData, change) => (0,_fastMerge__WEBPACK_IMPORTED_MODULE_10__["default"])(modifiedData, change),
|
|
1182
1166
|
existingValue || {});
|
|
1183
1167
|
}
|
|
1184
1168
|
|
|
@@ -1227,14 +1211,14 @@ function merge(key, changes) {
|
|
|
1227
1211
|
delete mergeQueuePromise[key];
|
|
1228
1212
|
|
|
1229
1213
|
// After that we merge the batched changes with the existing value
|
|
1230
|
-
const modifiedData = removeNullObjectValues(applyMerge(existingValue, [batchedChanges]));
|
|
1214
|
+
const modifiedData = _utils__WEBPACK_IMPORTED_MODULE_9__["default"].removeNullObjectValues(applyMerge(existingValue, [batchedChanges]));
|
|
1231
1215
|
|
|
1232
1216
|
// On native platforms we use SQLite which utilises JSON_PATCH to merge changes.
|
|
1233
1217
|
// JSON_PATCH generally removes top-level nullish values from the stored object.
|
|
1234
1218
|
// When there is no existing value though, SQLite will just insert the changes as a new value and thus the top-level nullish values won't be removed.
|
|
1235
1219
|
// Therefore we need to remove nullish values from the `batchedChanges` which are sent to the SQLite, if no existing value is present.
|
|
1236
1220
|
if (!existingValue) {
|
|
1237
|
-
batchedChanges = removeNullObjectValues(batchedChanges);
|
|
1221
|
+
batchedChanges = _utils__WEBPACK_IMPORTED_MODULE_9__["default"].removeNullObjectValues(batchedChanges);
|
|
1238
1222
|
}
|
|
1239
1223
|
|
|
1240
1224
|
const hasChanged = _OnyxCache__WEBPACK_IMPORTED_MODULE_3__["default"].hasValueChanged(key, modifiedData);
|
|
@@ -1268,7 +1252,7 @@ function initializeWithDefaultKeyStates() {
|
|
|
1268
1252
|
then((pairs) => {
|
|
1269
1253
|
const asObject = underscore__WEBPACK_IMPORTED_MODULE_1___default().object(pairs);
|
|
1270
1254
|
|
|
1271
|
-
const merged = (0,
|
|
1255
|
+
const merged = (0,_fastMerge__WEBPACK_IMPORTED_MODULE_10__["default"])(asObject, defaultKeyStates);
|
|
1272
1256
|
_OnyxCache__WEBPACK_IMPORTED_MODULE_3__["default"].merge(merged);
|
|
1273
1257
|
underscore__WEBPACK_IMPORTED_MODULE_1___default().each(merged, (val, key) => keyChanged(key, val));
|
|
1274
1258
|
});
|
|
@@ -1977,6 +1961,10 @@ __webpack_require__.r(__webpack_exports__);
|
|
|
1977
1961
|
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
|
1978
1962
|
/* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__)
|
|
1979
1963
|
/* harmony export */ });
|
|
1964
|
+
/* harmony import */ var underscore__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! underscore */ "underscore");
|
|
1965
|
+
/* harmony import */ var underscore__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(underscore__WEBPACK_IMPORTED_MODULE_0__);
|
|
1966
|
+
|
|
1967
|
+
|
|
1980
1968
|
// Mostly copied from https://medium.com/@lubaka.a/how-to-remove-lodash-performance-improvement-b306669ad0e1
|
|
1981
1969
|
|
|
1982
1970
|
/**
|
|
@@ -2033,10 +2021,7 @@ function mergeObject(target, source) {
|
|
|
2033
2021
|
* @returns {Object|Array}
|
|
2034
2022
|
*/
|
|
2035
2023
|
function fastMerge(target, source) {
|
|
2036
|
-
|
|
2037
|
-
// eslint-disable-next-line rulesdir/prefer-underscore-method
|
|
2038
|
-
const array = Array.isArray(source);
|
|
2039
|
-
if (array) {
|
|
2024
|
+
if (underscore__WEBPACK_IMPORTED_MODULE_0___default().isArray(source) || underscore__WEBPACK_IMPORTED_MODULE_0___default().isNull(source) || underscore__WEBPACK_IMPORTED_MODULE_0___default().isUndefined(source)) {
|
|
2040
2025
|
return source;
|
|
2041
2026
|
}
|
|
2042
2027
|
return mergeObject(target, source);
|
|
@@ -2282,6 +2267,8 @@ __webpack_require__.r(__webpack_exports__);
|
|
|
2282
2267
|
/* harmony import */ var underscore__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! underscore */ "underscore");
|
|
2283
2268
|
/* harmony import */ var underscore__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(underscore__WEBPACK_IMPORTED_MODULE_1__);
|
|
2284
2269
|
/* harmony import */ var _fastMerge__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../../fastMerge */ "./lib/fastMerge.js");
|
|
2270
|
+
/* harmony import */ var _utils__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../../utils */ "./lib/utils.js");
|
|
2271
|
+
|
|
2285
2272
|
|
|
2286
2273
|
|
|
2287
2274
|
|
|
@@ -2329,7 +2316,7 @@ const provider = {
|
|
|
2329
2316
|
const upsertMany = underscore__WEBPACK_IMPORTED_MODULE_1___default().map(pairs, (_ref2, index) => {let [key, value] = _ref2;
|
|
2330
2317
|
const prev = values[index];
|
|
2331
2318
|
const newValue = underscore__WEBPACK_IMPORTED_MODULE_1___default().isObject(prev) ? (0,_fastMerge__WEBPACK_IMPORTED_MODULE_2__["default"])(prev, value) : value;
|
|
2332
|
-
return (0,idb_keyval__WEBPACK_IMPORTED_MODULE_0__.promisifyRequest)(store.put(newValue, key));
|
|
2319
|
+
return (0,idb_keyval__WEBPACK_IMPORTED_MODULE_0__.promisifyRequest)(store.put(_utils__WEBPACK_IMPORTED_MODULE_3__["default"].removeNullObjectValues(newValue), key));
|
|
2333
2320
|
});
|
|
2334
2321
|
return Promise.all(upsertMany);
|
|
2335
2322
|
});
|
|
@@ -2414,6 +2401,45 @@ const provider = {
|
|
|
2414
2401
|
|
|
2415
2402
|
/***/ }),
|
|
2416
2403
|
|
|
2404
|
+
/***/ "./lib/utils.js":
|
|
2405
|
+
/*!**********************!*\
|
|
2406
|
+
!*** ./lib/utils.js ***!
|
|
2407
|
+
\**********************/
|
|
2408
|
+
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
|
2409
|
+
|
|
2410
|
+
"use strict";
|
|
2411
|
+
__webpack_require__.r(__webpack_exports__);
|
|
2412
|
+
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
|
2413
|
+
/* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__)
|
|
2414
|
+
/* harmony export */ });
|
|
2415
|
+
/* harmony import */ var underscore__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! underscore */ "underscore");
|
|
2416
|
+
/* harmony import */ var underscore__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(underscore__WEBPACK_IMPORTED_MODULE_0__);
|
|
2417
|
+
|
|
2418
|
+
|
|
2419
|
+
/**
|
|
2420
|
+
* We generally want to remove top-level nullish values from objects written to disk and cache, because it decreases the amount of data stored in memory and on disk.
|
|
2421
|
+
* On native, when merging an existing value with new changes, SQLite will use JSON_PATCH, which removes top-level nullish values.
|
|
2422
|
+
* To be consistent with the behaviour for merge, we'll also want to remove nullish values for "set" operations.
|
|
2423
|
+
* On web, IndexedDB will keep the top-level keys along with a null value and this uses up storage and memory.
|
|
2424
|
+
* This method will ensure that keys for null values are removed before an object is written to disk and cache so that all platforms are storing the data in the same efficient way.
|
|
2425
|
+
* @private
|
|
2426
|
+
* @param {*} value
|
|
2427
|
+
* @returns {*}
|
|
2428
|
+
*/
|
|
2429
|
+
function removeNullObjectValues(value) {
|
|
2430
|
+
if (underscore__WEBPACK_IMPORTED_MODULE_0___default().isArray(value) || !underscore__WEBPACK_IMPORTED_MODULE_0___default().isObject(value)) {
|
|
2431
|
+
return value;
|
|
2432
|
+
}
|
|
2433
|
+
|
|
2434
|
+
const objectWithoutNullObjectValues = underscore__WEBPACK_IMPORTED_MODULE_0___default().omit(value, (objectValue) => underscore__WEBPACK_IMPORTED_MODULE_0___default().isNull(objectValue));
|
|
2435
|
+
|
|
2436
|
+
return objectWithoutNullObjectValues;
|
|
2437
|
+
}
|
|
2438
|
+
|
|
2439
|
+
/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = ({ removeNullObjectValues });
|
|
2440
|
+
|
|
2441
|
+
/***/ }),
|
|
2442
|
+
|
|
2417
2443
|
/***/ "./lib/withOnyx.js":
|
|
2418
2444
|
/*!*************************!*\
|
|
2419
2445
|
!*** ./lib/withOnyx.js ***!
|