react-native-onyx 1.0.13 → 1.0.16

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 CHANGED
@@ -76,6 +76,7 @@ Subscribes a react component's state directly to a store key
76
76
  | [mapping.withOnyxInstance] | <code>Object</code> | whose setState() method will be called with any changed data This is used by React components to connect to Onyx |
77
77
  | [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 |
78
78
  | [mapping.initWithStoredValues] | <code>Boolean</code> | If set to false, then no data will be prefilled into the component |
79
+ | [mapping.waitForCollectionCallback] | <code>Boolean</code> | If set to true, it will return the entire collection to the callback as a single object |
79
80
 
80
81
  **Example**
81
82
  ```js
package/README.md CHANGED
@@ -63,7 +63,7 @@ The data will then be cached and stored via [`AsyncStorage`](https://github.com/
63
63
 
64
64
  We can also use `Onyx.merge()` to merge new `Object` or `Array` data in with existing data.
65
65
 
66
- For `Array` the default behavior is to concatenate new items.
66
+ For `Array` the default behavior is to concatenate replace it fully, effectively making it equivalent to set:
67
67
 
68
68
  ```javascript
69
69
  Onyx.merge(ONYXKEYS.EMPLOYEE_LIST, ['Joe']); // -> ['Joe']
@@ -77,20 +77,27 @@ Onyx.merge(ONYXKEYS.POLICY, {id: 1}); // -> {id: 1}
77
77
  Onyx.merge(ONYXKEYS.POLICY, {name: 'My Workspace'}); // -> {id: 1, name: 'My Workspace'}
78
78
  ```
79
79
 
80
- One caveat to be aware of is that `lodash/merge` [follows the behavior of jQuery's deep extend](https://github.com/lodash/lodash/issues/2872) and will not concatenate nested arrays in objects. It might seem like this code would concat these arrays, but it does not.
80
+ Arrays inside objects will NOT be concatenated and instead will be replaced fully, same as arrays not inside objects:
81
81
 
82
82
  ```javascript
83
- Onyx.merge(ONYXKEYS.POLICY, {employeeList: ['Joe']}); // -> {employeeList: ['Joe']}
83
+ Onyx.merge(ONYXKEYS.POLICY, {employeeList: ['Joe', 'Jack']}); // -> {employeeList: ['Joe', 'Jack']}
84
84
  Onyx.merge(ONYXKEYS.POLICY, {employeeList: ['Jack']}); // -> {employeeList: ['Jack']}
85
85
  ```
86
86
 
87
87
  ### Should I use `merge()` or `set()` or both?
88
88
 
89
- - Use `merge()` if we want to merge partial data into an existing `Array` or `Object`
90
- - Use `set()` if we are working with simple values (`String`, `Boolean`, etc), need to completely overwrite a complex property of an `Object`, or reset some data entirely.
89
+ - Use `merge()` when creating a new object
90
+ - Use `merge()` to merge partial data into an existing object
91
+ - Use `merge()` when storing simple values (`String`, `Boolean`, `Number`)
92
+ - Use `set()` when you need to delete an Onyx key completely from storage
93
+ - Use `set()` when you need to completely reset an object or array of data
91
94
 
92
95
  Consecutive calls to `Onyx.merge()` with the same key are batched in a stack and processed in the order that they were called. This helps avoid race conditions where one merge possibly finishes before another. However, it's important to note that calls to `Onyx.set()` are not batched together with calls to `Onyx.merge()`. For this reason, it is usually preferable to use one or the other, but not both. Onyx is a work-in-progress so always test code to make sure assumptions are correct!
93
96
 
97
+ ### Should I store things as an array or an object?
98
+
99
+ You should avoid arrays as much as possible. They do not work well with `merge()` because it can't update a single element in an array, it must always set the entire array each time. This forces you to use `set()` a lot, and as seen above, `merge()` is more performant and better to use in almost any situation. If you are working with an array of objects, then you should be using an Onyx collection because it's optimized for working with arrays of objects.
100
+
94
101
  ## Subscribing to data changes
95
102
 
96
103
  To set up a basic subscription for a given key use the `Onyx.connect()` method.
@@ -130,6 +137,80 @@ export default withOnyx({
130
137
 
131
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.
132
139
 
140
+ ## Collections
141
+
142
+ 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`).
143
+
144
+ ```javascript
145
+ const ONYXKEYS = {
146
+ COLLECTION: {
147
+ REPORT: 'report_',
148
+ },
149
+ };
150
+ ```
151
+
152
+ ### Setting Collection Values
153
+
154
+ To save a new collection key we can either do:
155
+
156
+ ```js
157
+ Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT}${report1.reportID}`, report1);
158
+ ```
159
+
160
+ or we can set many at once with `mergeCollection()` (see below for guidance on best practices):
161
+
162
+ ```js
163
+ Onyx.mergeCollection(ONYXKEYS.COLLECTION.REPORT, {
164
+ [`${ONYXKEYS.COLLECTION.REPORT}${report1.reportID}`]: report1,
165
+ [`${ONYXKEYS.COLLECTION.REPORT}${report2.reportID}`]: report2,
166
+ [`${ONYXKEYS.COLLECTION.REPORT}${report3.reportID}`]: report3,
167
+ });
168
+ ```
169
+
170
+ ### Subscribing to Collections
171
+
172
+ There are several ways to subscribe to these keys:
173
+
174
+ ```javascript
175
+ withOnyx({
176
+ allReports: {key: ONYXKEYS.COLLECTION.REPORT},
177
+ })(MyComponent);
178
+ ```
179
+
180
+ This will add a prop to the component called `allReports` which is an object of collection member key/values. Changes to the individual member keys will modify the entire object and new props will be passed with each individual key update. The prop doesn't update on the initial rendering of the component until the entire collection has been read out of Onyx.
181
+
182
+ ```js
183
+ Onyx.connect({key: ONYXKEYS.COLLECTION.REPORT}, callback: (memberValue, memberKey) => {...}});
184
+ ```
185
+
186
+ This will fire the callback once per member key depending on how many collection member keys are currently stored. Changes to those keys after the initial callbacks fire will occur when each individual key is updated.
187
+
188
+ ```js
189
+ Onyx.connect({
190
+ key: ONYXKEYS.COLLECTION.REPORT,
191
+ waitForCollectionCallback: true,
192
+ callback: (allReports) => {...}},
193
+ });
194
+ ```
195
+
196
+ This final option forces `Onyx.connect()` to behave more like `withOnyx()` and only update the callback once with the entire collection initially and later with an updated version of the collection when individual keys update.
197
+
198
+ ### Performance Considerations When Using Collections
199
+
200
+ Be cautious when using collections as things can get out of hand if you have a subscriber hooked up to a collection key that has large numbers of individual keys. If this is the case, it is critical to use `mergeCollection()` over `merge()`.
201
+
202
+ Remember, `mergeCollection()` will notify a subscriber only *once* with the total collected values whereas each call to `merge()` would re-render a connected component *each time it is called*. Consider this example where `reports` is an array of reports that we want to index and save.
203
+
204
+ ```js
205
+ // Bad
206
+ _.each(reports, report => Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT}${report.reportID}`, report)); // -> A component using withOnyx() will have it's state updated with each iteration
207
+
208
+ // Good
209
+ const values = {};
210
+ _.each(reports, report => values[`${ONYXKEYS.COLLECTION.REPORT}${report.reportID}`] = report);
211
+ Onyx.mergeCollection(ONYXKEYS.COLLECTION.REPORT, values); // -> A component using withOnyx() will only have it's state updated once
212
+ ```
213
+
133
214
  ## Clean up
134
215
 
135
216
  To clear all data from `Onyx` we can use `Onyx.clear()`.
@@ -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("lodash/merge"), require("lodash/get"), require("localforage"), require("react"));
3
+ module.exports = factory(require("underscore"), require("expensify-common/lib/str"), require("lodash/merge"), require("lodash/mergeWith"), require("lodash/get"), require("localforage"), require("react"));
4
4
  else if(typeof define === 'function' && define.amd)
5
- define(["underscore", "expensify-common/lib/str", "lodash/merge", "lodash/get", "localforage", "react"], factory);
5
+ define(["underscore", "expensify-common/lib/str", "lodash/merge", "lodash/mergeWith", "lodash/get", "localforage", "react"], factory);
6
6
  else if(typeof exports === 'object')
7
- exports["react-native-onyx/web"] = factory(require("underscore"), require("expensify-common/lib/str"), require("lodash/merge"), require("lodash/get"), require("localforage"), require("react"));
7
+ exports["react-native-onyx/web"] = factory(require("underscore"), require("expensify-common/lib/str"), require("lodash/merge"), require("lodash/mergeWith"), require("lodash/get"), require("localforage"), require("react"));
8
8
  else
9
- root["react-native-onyx/web"] = factory(root["underscore"], root["expensify-common/lib/str"], root["lodash/merge"], root["lodash/get"], root["localforage"], root["react"]);
10
- })(self, (__WEBPACK_EXTERNAL_MODULE_underscore__, __WEBPACK_EXTERNAL_MODULE_expensify_common_lib_str__, __WEBPACK_EXTERNAL_MODULE_lodash_merge__, __WEBPACK_EXTERNAL_MODULE_lodash_get__, __WEBPACK_EXTERNAL_MODULE_localforage__, __WEBPACK_EXTERNAL_MODULE_react__) => {
9
+ root["react-native-onyx/web"] = factory(root["underscore"], root["expensify-common/lib/str"], root["lodash/merge"], root["lodash/mergeWith"], root["lodash/get"], root["localforage"], root["react"]);
10
+ })(self, (__WEBPACK_EXTERNAL_MODULE_underscore__, __WEBPACK_EXTERNAL_MODULE_expensify_common_lib_str__, __WEBPACK_EXTERNAL_MODULE_lodash_merge__, __WEBPACK_EXTERNAL_MODULE_lodash_mergeWith__, __WEBPACK_EXTERNAL_MODULE_lodash_get__, __WEBPACK_EXTERNAL_MODULE_localforage__, __WEBPACK_EXTERNAL_MODULE_react__) => {
11
11
  return /******/ (() => { // webpackBootstrap
12
12
  /******/ var __webpack_modules__ = ({
13
13
 
@@ -492,11 +492,13 @@ function logInfo(message) {
492
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 _extends2 = _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"));var _underscore = _interopRequireDefault(__webpack_require__(/*! underscore */ "underscore"));
493
493
  var _str = _interopRequireDefault(__webpack_require__(/*! expensify-common/lib/str */ "expensify-common/lib/str"));
494
494
  var _merge = _interopRequireDefault(__webpack_require__(/*! lodash/merge */ "lodash/merge"));
495
+ var _mergeWith = _interopRequireDefault(__webpack_require__(/*! lodash/mergeWith */ "lodash/mergeWith"));
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"));
498
499
  var _OnyxCache = _interopRequireDefault(__webpack_require__(/*! ./OnyxCache */ "./lib/OnyxCache.js"));
499
- var _createDeferredTask = _interopRequireDefault(__webpack_require__(/*! ./createDeferredTask */ "./lib/createDeferredTask.js"));function _getRequireWildcardCache(nodeInterop) {if (typeof WeakMap !== "function") return null;var cacheBabelInterop = new WeakMap();var cacheNodeInterop = new WeakMap();return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) {return nodeInterop ? cacheNodeInterop : cacheBabelInterop;})(nodeInterop);}function _interopRequireWildcard(obj, nodeInterop) {if (!nodeInterop && obj && obj.__esModule) {return obj;}if (obj === null || typeof obj !== "object" && typeof obj !== "function") {return { default: obj };}var cache = _getRequireWildcardCache(nodeInterop);if (cache && cache.has(obj)) {return cache.get(obj);}var newObj = {};var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor;for (var key in obj) {if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) {var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null;if (desc && (desc.get || desc.set)) {Object.defineProperty(newObj, key, desc);} else {newObj[key] = obj[key];}}}newObj.default = obj;if (cache) {cache.set(obj, newObj);}return newObj;}
500
+ var _createDeferredTask = _interopRequireDefault(__webpack_require__(/*! ./createDeferredTask */ "./lib/createDeferredTask.js"));
501
+ var _customizerForMergeWith = _interopRequireDefault(__webpack_require__(/*! ./customizerForMergeWith */ "./lib/customizerForMergeWith.js"));function _getRequireWildcardCache(nodeInterop) {if (typeof WeakMap !== "function") return null;var cacheBabelInterop = new WeakMap();var cacheNodeInterop = new WeakMap();return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) {return nodeInterop ? cacheNodeInterop : cacheBabelInterop;})(nodeInterop);}function _interopRequireWildcard(obj, nodeInterop) {if (!nodeInterop && obj && obj.__esModule) {return obj;}if (obj === null || typeof obj !== "object" && typeof obj !== "function") {return { default: obj };}var cache = _getRequireWildcardCache(nodeInterop);if (cache && cache.has(obj)) {return cache.get(obj);}var newObj = {};var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor;for (var key in obj) {if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) {var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null;if (desc && (desc.get || desc.set)) {Object.defineProperty(newObj, key, desc);} else {newObj[key] = obj[key];}}}newObj.default = obj;if (cache) {cache.set(obj, newObj);}return newObj;}
500
502
 
501
503
  // Keeps track of the last connectionID that was used so we can keep incrementing it
502
504
  var lastConnectionID = 0;
@@ -744,8 +746,15 @@ function keysChanged(collectionKey, collection) {
744
746
  return;
745
747
  }
746
748
 
749
+ /**
750
+ * e.g. Onyx.connect({key: ONYXKEYS.COLLECTION.REPORT, callback: ...});
751
+ */
747
752
  var isSubscribedToCollectionKey = isKeyMatch(subscriber.key, collectionKey) &&
748
753
  isCollectionKey(subscriber.key);
754
+
755
+ /**
756
+ * e.g. Onyx.connect({key: `${ONYXKEYS.COLLECTION.REPORT}{reportID}`, callback: ...});
757
+ */
749
758
  var isSubscribedToCollectionMemberKey = subscriber.key.startsWith(collectionKey);
750
759
 
751
760
  if (isSubscribedToCollectionKey) {
@@ -819,7 +828,15 @@ function keyChanged(key, data) {
819
828
  }
820
829
 
821
830
  if (_underscore.default.isFunction(subscriber.callback)) {
831
+ if (subscriber.waitForCollectionCallback) {
832
+ var cachedCollection = getCachedCollection(subscriber.key);
833
+ cachedCollection[key] = data;
834
+ subscriber.callback(cachedCollection);
835
+ return;
836
+ }
837
+
822
838
  subscriber.callback(data, key);
839
+ return;
823
840
  }
824
841
 
825
842
  if (!subscriber.withOnyxInstance) {
@@ -888,7 +905,7 @@ function sendDataToConnection(config, val, key) {
888
905
  * This is used by any non-React code to connect to Onyx
889
906
  * @param {Boolean} [mapping.initWithStoredValues] If set to false, then no data will be prefilled into the
890
907
  * component
891
- * @param {Boolean} [mapping.waitForCollectionCallback] If set to true, it will trigger the callback once and return all data as a single object
908
+ * @param {Boolean} [mapping.waitForCollectionCallback] If set to true, it will return the entire collection to the callback as a single object
892
909
  * @returns {Number} an ID to use when calling disconnect
893
910
  */
894
911
  function connect(mapping) {
@@ -1137,7 +1154,7 @@ function applyMerge(key, data) {
1137
1154
  if (_underscore.default.isObject(data) || _underscore.default.every(mergeValues, _underscore.default.isObject)) {
1138
1155
  // Object values are merged one after the other
1139
1156
  return _underscore.default.reduce(mergeValues, function (modifiedData, mergeValue) {
1140
- var newData = (0, _merge.default)({}, modifiedData, mergeValue);
1157
+ var newData = (0, _mergeWith.default)({}, modifiedData, mergeValue, _customizerForMergeWith.default);
1141
1158
 
1142
1159
  // We will also delete any object keys that are undefined or null.
1143
1160
  // Deleting keys is not supported by AsyncStorage so we do it this way.
@@ -1208,7 +1225,7 @@ function initializeWithDefaultKeyStates() {
1208
1225
  then(function (pairs) {
1209
1226
  var asObject = _underscore.default.object(pairs);
1210
1227
 
1211
- var merged = (0, _merge.default)(asObject, defaultKeyStates);
1228
+ var merged = (0, _mergeWith.default)(asObject, defaultKeyStates, _customizerForMergeWith.default);
1212
1229
  _OnyxCache.default.merge(merged);
1213
1230
  _underscore.default.each(merged, function (val, key) {return keyChanged(key, val);});
1214
1231
  });
@@ -1478,7 +1495,8 @@ Onyx;exports["default"] = _default;
1478
1495
  /***/ ((__unused_webpack_module, exports, __webpack_require__) => {
1479
1496
 
1480
1497
  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 _toConsumableArray2 = _interopRequireDefault(__webpack_require__(/*! @babel/runtime/helpers/toConsumableArray */ "./node_modules/@babel/runtime/helpers/toConsumableArray.js"));var _classCallCheck2 = _interopRequireDefault(__webpack_require__(/*! @babel/runtime/helpers/classCallCheck */ "./node_modules/@babel/runtime/helpers/classCallCheck.js"));var _createClass2 = _interopRequireDefault(__webpack_require__(/*! @babel/runtime/helpers/createClass */ "./node_modules/@babel/runtime/helpers/createClass.js"));var _underscore = _interopRequireDefault(__webpack_require__(/*! underscore */ "underscore"));
1481
- var _merge = _interopRequireDefault(__webpack_require__(/*! lodash/merge */ "lodash/merge"));
1498
+ var _mergeWith = _interopRequireDefault(__webpack_require__(/*! lodash/mergeWith */ "lodash/mergeWith"));
1499
+ var _customizerForMergeWith = _interopRequireDefault(__webpack_require__(/*! ./customizerForMergeWith */ "./lib/customizerForMergeWith.js"));
1482
1500
 
1483
1501
  var isDefined = _underscore.default.negate(_underscore.default.isUndefined);
1484
1502
 
@@ -1589,7 +1607,7 @@ OnyxCache = /*#__PURE__*/function () {
1589
1607
  * @param {Record<string, *>} data - a map of (cache) key - values
1590
1608
  */ }, { key: "merge", value: function merge(
1591
1609
  data) {var _this = this;
1592
- this.storageMap = (0, _merge.default)({}, this.storageMap, data);
1610
+ this.storageMap = (0, _mergeWith.default)({}, this.storageMap, data, _customizerForMergeWith.default);
1593
1611
 
1594
1612
  var storageKeys = this.getAllKeys();
1595
1613
  var mergedKeys = _underscore.default.keys(data);
@@ -1760,6 +1778,36 @@ function createDeferredTask() {
1760
1778
 
1761
1779
  /***/ }),
1762
1780
 
1781
+ /***/ "./lib/customizerForMergeWith.js":
1782
+ /*!***************************************!*\
1783
+ !*** ./lib/customizerForMergeWith.js ***!
1784
+ \***************************************/
1785
+ /***/ ((__unused_webpack_module, exports, __webpack_require__) => {
1786
+
1787
+ 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 _underscore = _interopRequireDefault(__webpack_require__(/*! underscore */ "underscore"));
1788
+
1789
+ /**
1790
+ * When merging 2 objects into onyx that contain an array, we want to completely replace the array instead of the default
1791
+ * behavior which is to merge each item by its index.
1792
+ * ie:
1793
+ * merge({a: [1]}, {a: [2,3]}):
1794
+ * - In the default implementation would produce {a:[1,3]}
1795
+ * - With this function would produce: {a: [2,3]}
1796
+ * @param {*} objValue
1797
+ * @param {*} srcValue
1798
+ * @return {*}
1799
+ */
1800
+ // eslint-disable-next-line rulesdir/prefer-early-return
1801
+ function customizerForMergeWith(objValue, srcValue) {
1802
+ if (_underscore.default.isArray(objValue)) {
1803
+ return srcValue;
1804
+ }
1805
+ }var _default =
1806
+
1807
+ customizerForMergeWith;exports["default"] = _default;
1808
+
1809
+ /***/ }),
1810
+
1763
1811
  /***/ "./lib/metrics/index.web.js":
1764
1812
  /*!**********************************!*\
1765
1813
  !*** ./lib/metrics/index.web.js ***!
@@ -1866,8 +1914,9 @@ var _interopRequireDefault = __webpack_require__(/*! @babel/runtime/helpers/inte
1866
1914
 
1867
1915
  var _localforage = _interopRequireDefault(__webpack_require__(/*! localforage */ "localforage"));
1868
1916
  var _underscore = _interopRequireDefault(__webpack_require__(/*! underscore */ "underscore"));
1869
- var _merge = _interopRequireDefault(__webpack_require__(/*! lodash/merge */ "lodash/merge"));
1870
- var _SyncQueue = _interopRequireDefault(__webpack_require__(/*! ../../SyncQueue */ "./lib/SyncQueue.js")); /**
1917
+ var _mergeWith = _interopRequireDefault(__webpack_require__(/*! lodash/mergeWith */ "lodash/mergeWith"));
1918
+ var _SyncQueue = _interopRequireDefault(__webpack_require__(/*! ../../SyncQueue */ "./lib/SyncQueue.js"));
1919
+ var _customizerForMergeWith = _interopRequireDefault(__webpack_require__(/*! ../../customizerForMergeWith */ "./lib/customizerForMergeWith.js")); /**
1871
1920
  * @file
1872
1921
  * The storage provider based on localforage allows us to store most anything in its
1873
1922
  * natural form in the underlying DB without having to stringify or de-stringify it
@@ -1884,7 +1933,7 @@ var provider = {
1884
1933
  return _localforage.default.getItem(key).
1885
1934
  then(function (existingValue) {
1886
1935
  var newValue = _underscore.default.isObject(existingValue) ?
1887
- (0, _merge.default)({}, existingValue, value) :
1936
+ (0, _mergeWith.default)({}, existingValue, value, _customizerForMergeWith.default) :
1888
1937
  value;
1889
1938
  return _localforage.default.setItem(key, newValue);
1890
1939
  });
@@ -3297,6 +3346,17 @@ module.exports = __WEBPACK_EXTERNAL_MODULE_lodash_merge__;
3297
3346
 
3298
3347
  /***/ }),
3299
3348
 
3349
+ /***/ "lodash/mergeWith":
3350
+ /*!***********************************!*\
3351
+ !*** external "lodash/mergeWith" ***!
3352
+ \***********************************/
3353
+ /***/ ((module) => {
3354
+
3355
+ "use strict";
3356
+ module.exports = __WEBPACK_EXTERNAL_MODULE_lodash_mergeWith__;
3357
+
3358
+ /***/ }),
3359
+
3300
3360
  /***/ "react":
3301
3361
  /*!************************!*\
3302
3362
  !*** external "react" ***!