react-native-onyx 1.0.23 → 1.0.25
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/API.md +56 -21
- package/dist/web.development.js +142 -22
- 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 +131 -11
- package/lib/storage/index.native.js +2 -7
- package/package.json +1 -1
package/API.md
CHANGED
|
@@ -5,6 +5,14 @@
|
|
|
5
5
|
## Functions
|
|
6
6
|
|
|
7
7
|
<dl>
|
|
8
|
+
<dt><a href="#getSubsetOfData">getSubsetOfData(sourceData, selector)</a> ⇒ <code>Mixed</code></dt>
|
|
9
|
+
<dd><p>Uses a selector string or function to return a simplified version of sourceData</p>
|
|
10
|
+
</dd>
|
|
11
|
+
<dt><a href="#reduceCollectionWithSelector">reduceCollectionWithSelector(collection, selector)</a> ⇒ <code>Object</code></dt>
|
|
12
|
+
<dd><p>Takes a collection of items (eg. {testKey_1:{a:'a'}, testKey_2:{b:'b'}})
|
|
13
|
+
and runs it through a reducer function to return a subset of the data according to a selector.
|
|
14
|
+
The resulting collection will only contain items that are returned by the selector.</p>
|
|
15
|
+
</dd>
|
|
8
16
|
<dt><a href="#isCollectionMemberKey">isCollectionMemberKey(collectionKey, key)</a> ⇒ <code>Boolean</code></dt>
|
|
9
17
|
<dd></dd>
|
|
10
18
|
<dt><a href="#connect">connect(mapping)</a> ⇒ <code>Number</code></dt>
|
|
@@ -62,23 +70,49 @@ value will be saved to storage after the default value.</p>
|
|
|
62
70
|
</dd>
|
|
63
71
|
</dl>
|
|
64
72
|
|
|
73
|
+
<a name="getSubsetOfData"></a>
|
|
74
|
+
|
|
75
|
+
## getSubsetOfData(sourceData, selector) ⇒ <code>Mixed</code>
|
|
76
|
+
Uses a selector string or function to return a simplified version of sourceData
|
|
77
|
+
|
|
78
|
+
**Kind**: global function
|
|
79
|
+
|
|
80
|
+
| Param | Type | Description |
|
|
81
|
+
| --- | --- | --- |
|
|
82
|
+
| sourceData | <code>Mixed</code> | |
|
|
83
|
+
| selector | <code>String</code> \| <code>function</code> | If it's a string, the selector is passed to lodashGet on the sourceData If it's a function, it is passed the sourceData and it should return the simplified data |
|
|
84
|
+
|
|
85
|
+
<a name="reduceCollectionWithSelector"></a>
|
|
86
|
+
|
|
87
|
+
## reduceCollectionWithSelector(collection, selector) ⇒ <code>Object</code>
|
|
88
|
+
Takes a collection of items (eg. {testKey_1:{a:'a'}, testKey_2:{b:'b'}})
|
|
89
|
+
and runs it through a reducer function to return a subset of the data according to a selector.
|
|
90
|
+
The resulting collection will only contain items that are returned by the selector.
|
|
91
|
+
|
|
92
|
+
**Kind**: global function
|
|
93
|
+
|
|
94
|
+
| Param | Type | Description |
|
|
95
|
+
| --- | --- | --- |
|
|
96
|
+
| collection | <code>Object</code> | |
|
|
97
|
+
| selector | <code>String</code> \| <code>function</code> | (see method docs for getSubsetOfData() for full details) |
|
|
98
|
+
|
|
65
99
|
<a name="isCollectionMemberKey"></a>
|
|
66
100
|
|
|
67
101
|
## isCollectionMemberKey(collectionKey, key) ⇒ <code>Boolean</code>
|
|
68
|
-
**Kind**: global function
|
|
102
|
+
**Kind**: global function
|
|
69
103
|
|
|
70
104
|
| Param | Type |
|
|
71
105
|
| --- | --- |
|
|
72
|
-
| collectionKey | <code>String</code> |
|
|
73
|
-
| key | <code>String</code> |
|
|
106
|
+
| collectionKey | <code>String</code> |
|
|
107
|
+
| key | <code>String</code> |
|
|
74
108
|
|
|
75
109
|
<a name="connect"></a>
|
|
76
110
|
|
|
77
111
|
## connect(mapping) ⇒ <code>Number</code>
|
|
78
112
|
Subscribes a react component's state directly to a store key
|
|
79
113
|
|
|
80
|
-
**Kind**: global function
|
|
81
|
-
**Returns**: <code>Number</code> - an ID to use when calling disconnect
|
|
114
|
+
**Kind**: global function
|
|
115
|
+
**Returns**: <code>Number</code> - an ID to use when calling disconnect
|
|
82
116
|
|
|
83
117
|
| Param | Type | Description |
|
|
84
118
|
| --- | --- | --- |
|
|
@@ -89,8 +123,9 @@ Subscribes a react component's state directly to a store key
|
|
|
89
123
|
| [mapping.callback] | <code>function</code> | a method that will be called with changed data This is used by any non-React code to connect to Onyx |
|
|
90
124
|
| [mapping.initWithStoredValues] | <code>Boolean</code> | If set to false, then no data will be prefilled into the component |
|
|
91
125
|
| [mapping.waitForCollectionCallback] | <code>Boolean</code> | If set to true, it will return the entire collection to the callback as a single object |
|
|
126
|
+
| [mapping.selector] | <code>String</code> \| <code>function</code> | THIS PARAM IS ONLY USED WITH withOnyx(). If included, this will be used to subscribe to a subset of an Onyx key's data. If the selector is a string, the selector is passed to lodashGet on the sourceData. If the selector is a function, the sourceData is passed to the selector and should return the simplified data. Using this setting on `withOnyx` can have very positive performance benefits because the component will only re-render when the subset of data changes. Otherwise, any change of data on any property would normally cause the component to re-render (and that can be expensive from a performance standpoint). |
|
|
92
127
|
|
|
93
|
-
**Example**
|
|
128
|
+
**Example**
|
|
94
129
|
```js
|
|
95
130
|
const connectionID = Onyx.connect({
|
|
96
131
|
key: ONYXKEYS.SESSION,
|
|
@@ -102,14 +137,14 @@ const connectionID = Onyx.connect({
|
|
|
102
137
|
## disconnect(connectionID, [keyToRemoveFromEvictionBlocklist])
|
|
103
138
|
Remove the listener for a react component
|
|
104
139
|
|
|
105
|
-
**Kind**: global function
|
|
140
|
+
**Kind**: global function
|
|
106
141
|
|
|
107
142
|
| Param | Type | Description |
|
|
108
143
|
| --- | --- | --- |
|
|
109
144
|
| connectionID | <code>Number</code> | unique id returned by call to Onyx.connect() |
|
|
110
145
|
| [keyToRemoveFromEvictionBlocklist] | <code>String</code> | |
|
|
111
146
|
|
|
112
|
-
**Example**
|
|
147
|
+
**Example**
|
|
113
148
|
```js
|
|
114
149
|
Onyx.disconnect(connectionID);
|
|
115
150
|
```
|
|
@@ -121,7 +156,7 @@ For this reason, Onyx works more similar to what you might expect from a native
|
|
|
121
156
|
available async. Since we have code in our main applications that might expect things to work this way it's not safe to change this
|
|
122
157
|
behavior just yet.
|
|
123
158
|
|
|
124
|
-
**Kind**: global function
|
|
159
|
+
**Kind**: global function
|
|
125
160
|
|
|
126
161
|
| Param | Type | Description |
|
|
127
162
|
| --- | --- | --- |
|
|
@@ -129,7 +164,7 @@ behavior just yet.
|
|
|
129
164
|
| value | <code>\*</code> | |
|
|
130
165
|
| [canUpdateSubscriber] | <code>function</code> | only subscribers that pass this truth test will be updated |
|
|
131
166
|
|
|
132
|
-
**Example**
|
|
167
|
+
**Example**
|
|
133
168
|
```js
|
|
134
169
|
notifySubscribersOnNextTick(key, value, subscriber => subscriber.initWithStoredValues === false)
|
|
135
170
|
```
|
|
@@ -138,7 +173,7 @@ notifySubscribersOnNextTick(key, value, subscriber => subscriber.initWithStoredV
|
|
|
138
173
|
## set(key, value) ⇒ <code>Promise</code>
|
|
139
174
|
Write a value to our store with the given key
|
|
140
175
|
|
|
141
|
-
**Kind**: global function
|
|
176
|
+
**Kind**: global function
|
|
142
177
|
|
|
143
178
|
| Param | Type | Description |
|
|
144
179
|
| --- | --- | --- |
|
|
@@ -150,13 +185,13 @@ Write a value to our store with the given key
|
|
|
150
185
|
## multiSet(data) ⇒ <code>Promise</code>
|
|
151
186
|
Sets multiple keys and values
|
|
152
187
|
|
|
153
|
-
**Kind**: global function
|
|
188
|
+
**Kind**: global function
|
|
154
189
|
|
|
155
190
|
| Param | Type | Description |
|
|
156
191
|
| --- | --- | --- |
|
|
157
192
|
| data | <code>Object</code> | object keyed by ONYXKEYS and the values to set |
|
|
158
193
|
|
|
159
|
-
**Example**
|
|
194
|
+
**Example**
|
|
160
195
|
```js
|
|
161
196
|
Onyx.multiSet({'key1': 'a', 'key2': 'b'});
|
|
162
197
|
```
|
|
@@ -174,14 +209,14 @@ Calls to `Onyx.merge()` are batched so that any calls performed in a single tick
|
|
|
174
209
|
applied in the order they were called. Note: `Onyx.set()` calls do not work this way so use caution when mixing
|
|
175
210
|
`Onyx.merge()` and `Onyx.set()`.
|
|
176
211
|
|
|
177
|
-
**Kind**: global function
|
|
212
|
+
**Kind**: global function
|
|
178
213
|
|
|
179
214
|
| Param | Type | Description |
|
|
180
215
|
| --- | --- | --- |
|
|
181
216
|
| key | <code>String</code> | ONYXKEYS key |
|
|
182
217
|
| value | <code>Object</code> \| <code>Array</code> | Object or Array value to merge |
|
|
183
218
|
|
|
184
|
-
**Example**
|
|
219
|
+
**Example**
|
|
185
220
|
```js
|
|
186
221
|
Onyx.merge(ONYXKEYS.EMPLOYEE_LIST, ['Joe']); // -> ['Joe']
|
|
187
222
|
Onyx.merge(ONYXKEYS.EMPLOYEE_LIST, ['Jack']); // -> ['Joe', 'Jack']
|
|
@@ -209,20 +244,20 @@ Onyx.get(key) before calling Storage.setItem() via Onyx.set().
|
|
|
209
244
|
Storage.setItem() from Onyx.clear() will have already finished and the merged
|
|
210
245
|
value will be saved to storage after the default value.
|
|
211
246
|
|
|
212
|
-
**Kind**: global function
|
|
247
|
+
**Kind**: global function
|
|
213
248
|
<a name="mergeCollection"></a>
|
|
214
249
|
|
|
215
250
|
## mergeCollection(collectionKey, collection) ⇒ <code>Promise</code>
|
|
216
251
|
Merges a collection based on their keys
|
|
217
252
|
|
|
218
|
-
**Kind**: global function
|
|
253
|
+
**Kind**: global function
|
|
219
254
|
|
|
220
255
|
| Param | Type | Description |
|
|
221
256
|
| --- | --- | --- |
|
|
222
257
|
| collectionKey | <code>String</code> | e.g. `ONYXKEYS.COLLECTION.REPORT` |
|
|
223
258
|
| collection | <code>Object</code> | Object collection keyed by individual collection member keys and values |
|
|
224
259
|
|
|
225
|
-
**Example**
|
|
260
|
+
**Example**
|
|
226
261
|
```js
|
|
227
262
|
Onyx.mergeCollection(ONYXKEYS.COLLECTION.REPORT, {
|
|
228
263
|
[`${ONYXKEYS.COLLECTION.REPORT}1`]: report1,
|
|
@@ -234,7 +269,7 @@ Onyx.mergeCollection(ONYXKEYS.COLLECTION.REPORT, {
|
|
|
234
269
|
## update(data)
|
|
235
270
|
Insert API responses and lifecycle data into Onyx
|
|
236
271
|
|
|
237
|
-
**Kind**: global function
|
|
272
|
+
**Kind**: global function
|
|
238
273
|
|
|
239
274
|
| Param | Type | Description |
|
|
240
275
|
| --- | --- | --- |
|
|
@@ -245,7 +280,7 @@ Insert API responses and lifecycle data into Onyx
|
|
|
245
280
|
## init([options])
|
|
246
281
|
Initialize the store with actions and listening for storage events
|
|
247
282
|
|
|
248
|
-
**Kind**: global function
|
|
283
|
+
**Kind**: global function
|
|
249
284
|
|
|
250
285
|
| Param | Type | Default | Description |
|
|
251
286
|
| --- | --- | --- | --- |
|
|
@@ -258,7 +293,7 @@ Initialize the store with actions and listening for storage events
|
|
|
258
293
|
| [options.shouldSyncMultipleInstances] | <code>Boolean</code> | | Auto synchronize storage events between multiple instances of Onyx running in different tabs/windows. Defaults to true for platforms that support local storage (web/desktop) |
|
|
259
294
|
| [options.debugSetState] | <code>Boolean</code> | | Enables debugging setState() calls to connected components. |
|
|
260
295
|
|
|
261
|
-
**Example**
|
|
296
|
+
**Example**
|
|
262
297
|
```js
|
|
263
298
|
Onyx.init({
|
|
264
299
|
keys: ONYXKEYS,
|
package/dist/web.development.js
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
(function webpackUniversalModuleDefinition(root, factory) {
|
|
2
2
|
if(typeof exports === 'object' && typeof module === 'object')
|
|
3
|
-
module.exports = factory(require("underscore"), require("expensify-common/lib/str"), require("
|
|
3
|
+
module.exports = factory(require("underscore"), require("expensify-common/lib/str"), require("fast-equals"), require("lodash/get"), require("localforage"), require("lodash/transform"), require("react"));
|
|
4
4
|
else if(typeof define === 'function' && define.amd)
|
|
5
|
-
define(["underscore", "expensify-common/lib/str", "lodash/get", "localforage", "
|
|
5
|
+
define(["underscore", "expensify-common/lib/str", "fast-equals", "lodash/get", "localforage", "lodash/transform", "react"], factory);
|
|
6
6
|
else if(typeof exports === 'object')
|
|
7
|
-
exports["react-native-onyx/web"] = factory(require("underscore"), require("expensify-common/lib/str"), require("
|
|
7
|
+
exports["react-native-onyx/web"] = factory(require("underscore"), require("expensify-common/lib/str"), require("fast-equals"), require("lodash/get"), require("localforage"), require("lodash/transform"), require("react"));
|
|
8
8
|
else
|
|
9
|
-
root["react-native-onyx/web"] = factory(root["underscore"], root["expensify-common/lib/str"], root["
|
|
10
|
-
})(self, (__WEBPACK_EXTERNAL_MODULE_underscore__, __WEBPACK_EXTERNAL_MODULE_expensify_common_lib_str__, __WEBPACK_EXTERNAL_MODULE_lodash_get__, __WEBPACK_EXTERNAL_MODULE_localforage__,
|
|
9
|
+
root["react-native-onyx/web"] = factory(root["underscore"], root["expensify-common/lib/str"], root["fast-equals"], root["lodash/get"], root["localforage"], root["lodash/transform"], root["react"]);
|
|
10
|
+
})(self, (__WEBPACK_EXTERNAL_MODULE_underscore__, __WEBPACK_EXTERNAL_MODULE_expensify_common_lib_str__, __WEBPACK_EXTERNAL_MODULE_fast_equals__, __WEBPACK_EXTERNAL_MODULE_lodash_get__, __WEBPACK_EXTERNAL_MODULE_localforage__, __WEBPACK_EXTERNAL_MODULE_lodash_transform__, __WEBPACK_EXTERNAL_MODULE_react__) => {
|
|
11
11
|
return /******/ (() => { // webpackBootstrap
|
|
12
12
|
/******/ var __webpack_modules__ = ({
|
|
13
13
|
|
|
@@ -489,9 +489,10 @@ function logInfo(message) {
|
|
|
489
489
|
\*********************/
|
|
490
490
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
491
491
|
|
|
492
|
-
var _interopRequireDefault = __webpack_require__(/*! @babel/runtime/helpers/interopRequireDefault */ "./node_modules/@babel/runtime/helpers/interopRequireDefault.js");Object.defineProperty(exports, "__esModule", ({ value: true }));exports["default"] = void 0;var _slicedToArray2 = _interopRequireDefault(__webpack_require__(/*! @babel/runtime/helpers/slicedToArray */ "./node_modules/@babel/runtime/helpers/slicedToArray.js"));var _toConsumableArray2 = _interopRequireDefault(__webpack_require__(/*! @babel/runtime/helpers/toConsumableArray */ "./node_modules/@babel/runtime/helpers/toConsumableArray.js"));var
|
|
492
|
+
var _interopRequireDefault = __webpack_require__(/*! @babel/runtime/helpers/interopRequireDefault */ "./node_modules/@babel/runtime/helpers/interopRequireDefault.js");Object.defineProperty(exports, "__esModule", ({ value: true }));exports["default"] = void 0;var _slicedToArray2 = _interopRequireDefault(__webpack_require__(/*! @babel/runtime/helpers/slicedToArray */ "./node_modules/@babel/runtime/helpers/slicedToArray.js"));var _toConsumableArray2 = _interopRequireDefault(__webpack_require__(/*! @babel/runtime/helpers/toConsumableArray */ "./node_modules/@babel/runtime/helpers/toConsumableArray.js"));var _extends4 = _interopRequireDefault(__webpack_require__(/*! @babel/runtime/helpers/extends */ "./node_modules/@babel/runtime/helpers/extends.js"));var _defineProperty2 = _interopRequireDefault(__webpack_require__(/*! @babel/runtime/helpers/defineProperty */ "./node_modules/@babel/runtime/helpers/defineProperty.js"));
|
|
493
493
|
var _underscore = _interopRequireDefault(__webpack_require__(/*! underscore */ "underscore"));
|
|
494
494
|
var _str = _interopRequireDefault(__webpack_require__(/*! expensify-common/lib/str */ "expensify-common/lib/str"));
|
|
495
|
+
var _fastEquals = __webpack_require__(/*! fast-equals */ "fast-equals");
|
|
495
496
|
var _get = _interopRequireDefault(__webpack_require__(/*! lodash/get */ "lodash/get"));
|
|
496
497
|
var _storage = _interopRequireDefault(__webpack_require__(/*! ./storage */ "./lib/storage/index.web.js"));
|
|
497
498
|
var Logger = _interopRequireWildcard(__webpack_require__(/*! ./Logger */ "./lib/Logger.js"));
|
|
@@ -526,6 +527,33 @@ var defaultKeyStates = {};
|
|
|
526
527
|
// Connections can be made before `Onyx.init`. They would wait for this task before resolving
|
|
527
528
|
var deferredInitTask = (0, _createDeferredTask.default)();
|
|
528
529
|
|
|
530
|
+
/**
|
|
531
|
+
* Uses a selector string or function to return a simplified version of sourceData
|
|
532
|
+
* @param {Mixed} sourceData
|
|
533
|
+
* @param {String|Function} selector
|
|
534
|
+
* If it's a string, the selector is passed to lodashGet on the sourceData
|
|
535
|
+
* If it's a function, it is passed the sourceData and it should return the simplified data
|
|
536
|
+
* @returns {Mixed}
|
|
537
|
+
*/
|
|
538
|
+
var getSubsetOfData = function getSubsetOfData(sourceData, selector) {return _underscore.default.isFunction(selector) ?
|
|
539
|
+
selector(sourceData) :
|
|
540
|
+
(0, _get.default)(sourceData, selector);};
|
|
541
|
+
|
|
542
|
+
/**
|
|
543
|
+
* Takes a collection of items (eg. {testKey_1:{a:'a'}, testKey_2:{b:'b'}})
|
|
544
|
+
* and runs it through a reducer function to return a subset of the data according to a selector.
|
|
545
|
+
* The resulting collection will only contain items that are returned by the selector.
|
|
546
|
+
* @param {Object} collection
|
|
547
|
+
* @param {String|Function} selector (see method docs for getSubsetOfData() for full details)
|
|
548
|
+
* @returns {Object}
|
|
549
|
+
*/
|
|
550
|
+
var reduceCollectionWithSelector = function reduceCollectionWithSelector(collection, selector) {return _underscore.default.reduce(collection, function (finalCollection, item, key) {
|
|
551
|
+
// eslint-disable-next-line no-param-reassign
|
|
552
|
+
finalCollection[key] = getSubsetOfData(item, selector);
|
|
553
|
+
|
|
554
|
+
return finalCollection;
|
|
555
|
+
}, {});};
|
|
556
|
+
|
|
529
557
|
/**
|
|
530
558
|
* Get some data from the store
|
|
531
559
|
*
|
|
@@ -813,6 +841,23 @@ function keysChanged(collectionKey, partialCollection) {
|
|
|
813
841
|
// We are subscribed to a collection key so we must update the data in state with the new
|
|
814
842
|
// collection member key values from the partial update.
|
|
815
843
|
if (isSubscribedToCollectionKey) {
|
|
844
|
+
// If the subscriber has a selector, then the component's state must only be updated with the data
|
|
845
|
+
// returned by the selector.
|
|
846
|
+
if (subscriber.selector) {
|
|
847
|
+
subscriber.withOnyxInstance.setState(function (prevState) {
|
|
848
|
+
var previousData = reduceCollectionWithSelector(prevState[subscriber.statePropertyName], subscriber.selector);
|
|
849
|
+
var newData = reduceCollectionWithSelector(cachedCollection, subscriber.selector);
|
|
850
|
+
|
|
851
|
+
if (!(0, _fastEquals.deepEqual)(previousData, newData)) {
|
|
852
|
+
return (0, _defineProperty2.default)({},
|
|
853
|
+
subscriber.statePropertyName, newData);
|
|
854
|
+
|
|
855
|
+
}
|
|
856
|
+
return null;
|
|
857
|
+
});
|
|
858
|
+
return "continue";
|
|
859
|
+
}
|
|
860
|
+
|
|
816
861
|
subscriber.withOnyxInstance.setState(function (prevState) {
|
|
817
862
|
var finalCollection = _underscore.default.clone(prevState[subscriber.statePropertyName] || {});
|
|
818
863
|
var dataKeys = _underscore.default.keys(partialCollection);
|
|
@@ -838,6 +883,25 @@ function keysChanged(collectionKey, partialCollection) {
|
|
|
838
883
|
return "continue";
|
|
839
884
|
}
|
|
840
885
|
|
|
886
|
+
// If the subscriber has a selector, then the component's state must only be updated with the data
|
|
887
|
+
// returned by the selector and the state should only change when the subset of data changes from what
|
|
888
|
+
// it was previously.
|
|
889
|
+
if (subscriber.selector) {
|
|
890
|
+
subscriber.withOnyxInstance.setState(function (prevState) {
|
|
891
|
+
var prevData = prevState[subscriber.statePropertyName];
|
|
892
|
+
var newData = getSubsetOfData(cachedCollection[subscriber.key], subscriber.selector);
|
|
893
|
+
if (!(0, _fastEquals.deepEqual)(prevData, newData)) {
|
|
894
|
+
PerformanceUtils.logSetStateCall(subscriber, prevData, newData, 'keysChanged', collectionKey);
|
|
895
|
+
return (0, _defineProperty2.default)({},
|
|
896
|
+
subscriber.statePropertyName, newData);
|
|
897
|
+
|
|
898
|
+
}
|
|
899
|
+
|
|
900
|
+
return null;
|
|
901
|
+
});
|
|
902
|
+
return "continue";
|
|
903
|
+
}
|
|
904
|
+
|
|
841
905
|
subscriber.withOnyxInstance.setState(function (prevState) {
|
|
842
906
|
var data = cachedCollection[subscriber.key];
|
|
843
907
|
var previousData = prevState[subscriber.statePropertyName];
|
|
@@ -901,9 +965,32 @@ function keyChanged(key, data, canUpdateSubscriber) {
|
|
|
901
965
|
if (subscriber.withOnyxInstance) {
|
|
902
966
|
// Check if we are subscribing to a collection key and overwrite the collection member key value in state
|
|
903
967
|
if (isCollectionKey(subscriber.key)) {
|
|
968
|
+
// If the subscriber has a selector, then the consumer of this data must only be given the data
|
|
969
|
+
// returned by the selector and only when the selected data has changed.
|
|
970
|
+
if (subscriber.selector) {
|
|
971
|
+
subscriber.withOnyxInstance.setState(function (prevState) {
|
|
972
|
+
var prevData = prevState[subscriber.statePropertyName];
|
|
973
|
+
var newData = (0, _defineProperty2.default)({},
|
|
974
|
+
key, getSubsetOfData(data, subscriber.selector));
|
|
975
|
+
|
|
976
|
+
var prevDataWithNewData = (0, _extends4.default)({},
|
|
977
|
+
prevData, (0, _defineProperty2.default)({},
|
|
978
|
+
key, getSubsetOfData(data, subscriber.selector)));
|
|
979
|
+
|
|
980
|
+
if (!(0, _fastEquals.deepEqual)(prevData, prevDataWithNewData)) {
|
|
981
|
+
PerformanceUtils.logSetStateCall(subscriber, prevData, newData, 'keyChanged', key);
|
|
982
|
+
return (0, _defineProperty2.default)({},
|
|
983
|
+
subscriber.statePropertyName, prevDataWithNewData);
|
|
984
|
+
|
|
985
|
+
}
|
|
986
|
+
return null;
|
|
987
|
+
});
|
|
988
|
+
return "continue";
|
|
989
|
+
}
|
|
990
|
+
|
|
904
991
|
subscriber.withOnyxInstance.setState(function (prevState) {
|
|
905
992
|
var collection = prevState[subscriber.statePropertyName] || {};
|
|
906
|
-
var newCollection = (0,
|
|
993
|
+
var newCollection = (0, _extends4.default)({},
|
|
907
994
|
collection, (0, _defineProperty2.default)({},
|
|
908
995
|
key, data));
|
|
909
996
|
|
|
@@ -915,6 +1002,22 @@ function keyChanged(key, data, canUpdateSubscriber) {
|
|
|
915
1002
|
return "continue";
|
|
916
1003
|
}
|
|
917
1004
|
|
|
1005
|
+
// If the subscriber has a selector, then the component's state must only be updated with the data
|
|
1006
|
+
// returned by the selector and only if the selected data has changed.
|
|
1007
|
+
if (subscriber.selector) {
|
|
1008
|
+
subscriber.withOnyxInstance.setState(function (prevState) {
|
|
1009
|
+
var previousValue = getSubsetOfData(prevState, subscriber.selector);
|
|
1010
|
+
var newValue = getSubsetOfData(data, subscriber.selector);
|
|
1011
|
+
if (!(0, _fastEquals.deepEqual)(previousValue, newValue)) {
|
|
1012
|
+
return (0, _defineProperty2.default)({},
|
|
1013
|
+
subscriber.statePropertyName, newValue);
|
|
1014
|
+
|
|
1015
|
+
}
|
|
1016
|
+
return null;
|
|
1017
|
+
});
|
|
1018
|
+
return "continue";
|
|
1019
|
+
}
|
|
1020
|
+
|
|
918
1021
|
// If we did not match on a collection key then we just set the new data to the state property
|
|
919
1022
|
subscriber.withOnyxInstance.setState(function (prevState) {
|
|
920
1023
|
var previousData = prevState[subscriber.statePropertyName];
|
|
@@ -940,25 +1043,41 @@ function keyChanged(key, data, canUpdateSubscriber) {
|
|
|
940
1043
|
* - triggers the callback function
|
|
941
1044
|
*
|
|
942
1045
|
* @private
|
|
943
|
-
* @param {
|
|
944
|
-
* @param {
|
|
945
|
-
* @param {
|
|
946
|
-
* @param {
|
|
1046
|
+
* @param {Object} mapping
|
|
1047
|
+
* @param {Object} [mapping.withOnyxInstance]
|
|
1048
|
+
* @param {String} [mapping.statePropertyName]
|
|
1049
|
+
* @param {Function} [mapping.callback]
|
|
1050
|
+
* @param {String} [mapping.selector]
|
|
947
1051
|
* @param {*|null} val
|
|
948
1052
|
* @param {String} matchedKey
|
|
949
1053
|
*/
|
|
950
|
-
function sendDataToConnection(
|
|
1054
|
+
function sendDataToConnection(mapping, val, matchedKey) {
|
|
951
1055
|
// If the mapping no longer exists then we should not send any data.
|
|
952
1056
|
// This means our subscriber disconnected or withOnyx wrapped component unmounted.
|
|
953
|
-
if (!callbackToStateMapping[
|
|
1057
|
+
if (!callbackToStateMapping[mapping.connectionID]) {
|
|
1058
|
+
return;
|
|
1059
|
+
}
|
|
1060
|
+
|
|
1061
|
+
if (mapping.withOnyxInstance) {
|
|
1062
|
+
var newData = val;
|
|
1063
|
+
|
|
1064
|
+
// If the mapping has a selector, then the component's state must only be updated with the data
|
|
1065
|
+
// returned by the selector.
|
|
1066
|
+
if (mapping.selector) {
|
|
1067
|
+
if (isCollectionKey(mapping.key)) {
|
|
1068
|
+
newData = reduceCollectionWithSelector(val, mapping.selector);
|
|
1069
|
+
} else {
|
|
1070
|
+
newData = getSubsetOfData(val, mapping.selector);
|
|
1071
|
+
}
|
|
1072
|
+
}
|
|
1073
|
+
|
|
1074
|
+
PerformanceUtils.logSetStateCall(mapping, null, newData, 'sendDataToConnection');
|
|
1075
|
+
mapping.withOnyxInstance.setWithOnyxState(mapping.statePropertyName, newData);
|
|
954
1076
|
return;
|
|
955
1077
|
}
|
|
956
1078
|
|
|
957
|
-
if (
|
|
958
|
-
|
|
959
|
-
config.withOnyxInstance.setWithOnyxState(config.statePropertyName, val);
|
|
960
|
-
} else if (_underscore.default.isFunction(config.callback)) {
|
|
961
|
-
config.callback(val, matchedKey);
|
|
1079
|
+
if (_underscore.default.isFunction(mapping.callback)) {
|
|
1080
|
+
mapping.callback(val, matchedKey);
|
|
962
1081
|
}
|
|
963
1082
|
}
|
|
964
1083
|
|
|
@@ -1025,6 +1144,7 @@ function getCollectionDataAndSendAsObject(matchingKeys, mapping) {
|
|
|
1025
1144
|
* @param {Boolean} [mapping.initWithStoredValues] If set to false, then no data will be prefilled into the
|
|
1026
1145
|
* component
|
|
1027
1146
|
* @param {Boolean} [mapping.waitForCollectionCallback] If set to true, it will return the entire collection to the callback as a single object
|
|
1147
|
+
* @param {String|Function} [mapping.selector] THIS PARAM IS ONLY USED WITH withOnyx(). If included, this will be used to subscribe to a subset of an Onyx key's data. If the selector is a string, the selector is passed to lodashGet on the sourceData. If the selector is a function, the sourceData is passed to the selector and should return the simplified data. Using this setting on `withOnyx` can have very positive performance benefits because the component will only re-render when the subset of data changes. Otherwise, any change of data on any property would normally cause the component to re-render (and that can be expensive from a performance standpoint).
|
|
1028
1148
|
* @returns {Number} an ID to use when calling disconnect
|
|
1029
1149
|
*/
|
|
1030
1150
|
function connect(mapping) {
|
|
@@ -1292,7 +1412,7 @@ function applyMerge(key, data) {
|
|
|
1292
1412
|
return _underscore.default.reduce(mergeValues, function (modifiedData, mergeValue) {
|
|
1293
1413
|
// lodash adds a small overhead so we don't use it here
|
|
1294
1414
|
// eslint-disable-next-line prefer-object-spread, rulesdir/prefer-underscore-method
|
|
1295
|
-
var newData = (0,
|
|
1415
|
+
var newData = (0, _extends4.default)({}, (0, _fastMerge.default)(modifiedData, mergeValue));
|
|
1296
1416
|
|
|
1297
1417
|
// We will also delete any object keys that are undefined or null.
|
|
1298
1418
|
// Deleting keys is not supported by AsyncStorage so we do it this way.
|
|
@@ -1470,7 +1590,7 @@ function mergeCollection(collectionKey, collection) {
|
|
|
1470
1590
|
*/
|
|
1471
1591
|
function update(data) {
|
|
1472
1592
|
// First, validate the Onyx object is in the format we expect
|
|
1473
|
-
_underscore.default.each(data, function (
|
|
1593
|
+
_underscore.default.each(data, function (_ref9) {var onyxMethod = _ref9.onyxMethod,key = _ref9.key;
|
|
1474
1594
|
if (!_underscore.default.contains(['clear', 'set', 'merge', 'mergecollection'], onyxMethod)) {
|
|
1475
1595
|
throw new Error("Invalid onyxMethod " + onyxMethod + " in Onyx update.");
|
|
1476
1596
|
}
|
|
@@ -1479,7 +1599,7 @@ function update(data) {
|
|
|
1479
1599
|
}
|
|
1480
1600
|
});
|
|
1481
1601
|
|
|
1482
|
-
_underscore.default.each(data, function (
|
|
1602
|
+
_underscore.default.each(data, function (_ref10) {var onyxMethod = _ref10.onyxMethod,key = _ref10.key,value = _ref10.value;
|
|
1483
1603
|
switch (onyxMethod) {
|
|
1484
1604
|
case 'set':
|
|
1485
1605
|
set(key, value);
|
|
@@ -1532,7 +1652,7 @@ function init()
|
|
|
1532
1652
|
|
|
1533
1653
|
|
|
1534
1654
|
|
|
1535
|
-
{var
|
|
1655
|
+
{var _ref11 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},_ref11$keys = _ref11.keys,keys = _ref11$keys === void 0 ? {} : _ref11$keys,_ref11$initialKeyStat = _ref11.initialKeyStates,initialKeyStates = _ref11$initialKeyStat === void 0 ? {} : _ref11$initialKeyStat,_ref11$safeEvictionKe = _ref11.safeEvictionKeys,safeEvictionKeys = _ref11$safeEvictionKe === void 0 ? [] : _ref11$safeEvictionKe,_ref11$maxCachedKeysC = _ref11.maxCachedKeysCount,maxCachedKeysCount = _ref11$maxCachedKeysC === void 0 ? 1000 : _ref11$maxCachedKeysC,_ref11$captureMetrics = _ref11.captureMetrics,captureMetrics = _ref11$captureMetrics === void 0 ? false : _ref11$captureMetrics,_ref11$shouldSyncMult = _ref11.shouldSyncMultipleInstances,shouldSyncMultipleInstances = _ref11$shouldSyncMult === void 0 ? Boolean(__webpack_require__.g.localStorage) : _ref11$shouldSyncMult,_ref11$debugSetState = _ref11.debugSetState,debugSetState = _ref11$debugSetState === void 0 ? false : _ref11$debugSetState;
|
|
1536
1656
|
if (captureMetrics) {
|
|
1537
1657
|
// The code here is only bundled and applied when the captureMetrics is set
|
|
1538
1658
|
// eslint-disable-next-line no-use-before-define
|