react-native-onyx 1.0.57 → 1.0.59

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.
@@ -991,6 +991,24 @@ function hasPendingMergeForKey(key) {
991
991
  return Boolean(mergeQueue[key]);
992
992
  }
993
993
 
994
+ /**
995
+ * 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.
996
+ * On native, when merging an existing value with new changes, SQLite will use JSON_PATCH, which removes top-level nullish values.
997
+ * To be consistent with the behaviour for merge, we'll also want to remove nullish values for "set" operations.
998
+ * On web, IndexedDB will keep the top-level keys along with a null value and this uses up storage and memory.
999
+ * 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.
1000
+ * @private
1001
+ * @param {*} value
1002
+ * @returns {*}
1003
+ */
1004
+ function removeNullObjectValues(value) {
1005
+ if (underscore__WEBPACK_IMPORTED_MODULE_1___default().isArray(value) || !underscore__WEBPACK_IMPORTED_MODULE_1___default().isObject(value)) {
1006
+ return value;
1007
+ }
1008
+
1009
+ return underscore__WEBPACK_IMPORTED_MODULE_1___default().omit(value, (objectValue) => underscore__WEBPACK_IMPORTED_MODULE_1___default().isNull(objectValue));
1010
+ }
1011
+
994
1012
  /**
995
1013
  * Write a value to our store with the given key
996
1014
  *
@@ -1008,18 +1026,20 @@ function set(key, value) {
1008
1026
  _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.`);
1009
1027
  }
1010
1028
 
1011
- const hasChanged = _OnyxCache__WEBPACK_IMPORTED_MODULE_3__["default"].hasValueChanged(key, value);
1029
+ const valueWithNullRemoved = removeNullObjectValues(value);
1030
+
1031
+ const hasChanged = _OnyxCache__WEBPACK_IMPORTED_MODULE_3__["default"].hasValueChanged(key, valueWithNullRemoved);
1012
1032
 
1013
1033
  // This approach prioritizes fast UI changes without waiting for data to be stored in device storage.
1014
- broadcastUpdate(key, value, hasChanged, 'set');
1034
+ broadcastUpdate(key, valueWithNullRemoved, hasChanged, 'set');
1015
1035
 
1016
1036
  // If the value has not changed, calling Storage.setItem() would be redundant and a waste of performance, so return early instead.
1017
1037
  if (!hasChanged) {
1018
1038
  return Promise.resolve();
1019
1039
  }
1020
1040
 
1021
- return _storage__WEBPACK_IMPORTED_MODULE_4__["default"].setItem(key, value).
1022
- catch((error) => evictStorageAndRetry(error, set, key, value));
1041
+ return _storage__WEBPACK_IMPORTED_MODULE_4__["default"].setItem(key, valueWithNullRemoved).
1042
+ catch((error) => evictStorageAndRetry(error, set, key, valueWithNullRemoved));
1023
1043
  }
1024
1044
 
1025
1045
  /**
@@ -1116,19 +1136,21 @@ function merge(key, changes) {
1116
1136
  then((existingValue) => {
1117
1137
  try {
1118
1138
  // We first only merge the changes, so we can provide these to the native implementation (SQLite uses only delta changes in "JSON_PATCH" to merge)
1119
- const batchedChanges = applyMerge(undefined, mergeQueue[key]);
1139
+ let batchedChanges = applyMerge(undefined, mergeQueue[key]);
1120
1140
 
1121
1141
  // Clean up the write queue so we
1122
1142
  // don't apply these changes again
1123
1143
  delete mergeQueue[key];
1124
1144
 
1125
1145
  // After that we merge the batched changes with the existing value
1126
- let modifiedData = applyMerge(existingValue, [batchedChanges]);
1127
-
1128
- // For objects, the key for null values needs to be removed from the object to ensure the value will get removed from storage completely.
1129
- // On native, SQLite will remove top-level keys that are null. To be consistent, we remove them on web too.
1130
- if (!underscore__WEBPACK_IMPORTED_MODULE_1___default().isArray(modifiedData) && underscore__WEBPACK_IMPORTED_MODULE_1___default().isObject(modifiedData)) {
1131
- modifiedData = underscore__WEBPACK_IMPORTED_MODULE_1___default().omit(modifiedData, (value) => underscore__WEBPACK_IMPORTED_MODULE_1___default().isNull(value));
1146
+ const modifiedData = removeNullObjectValues(applyMerge(existingValue, [batchedChanges]));
1147
+
1148
+ // On native platforms we use SQLite which utilises JSON_PATCH to merge changes.
1149
+ // JSON_PATCH generally removes top-level nullish values from the stored object.
1150
+ // 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.
1151
+ // Therefore we need to remove nullish values from the `batchedChanges` which are sent to the SQLite, if no existing value is present.
1152
+ if (!existingValue) {
1153
+ batchedChanges = removeNullObjectValues(batchedChanges);
1132
1154
  }
1133
1155
 
1134
1156
  const hasChanged = _OnyxCache__WEBPACK_IMPORTED_MODULE_3__["default"].hasValueChanged(key, modifiedData);
@@ -1458,7 +1480,6 @@ const Onyx = {
1458
1480
  multiSet,
1459
1481
  merge,
1460
1482
  mergeCollection,
1461
- hasPendingMergeForKey,
1462
1483
  update,
1463
1484
  clear,
1464
1485
  getAllKeys,
@@ -2611,7 +2632,8 @@ function getDisplayName(component) {
2611
2632
  withOnyx.propTypes = {
2612
2633
  forwardedRef: prop_types__WEBPACK_IMPORTED_MODULE_0___default().oneOfType([
2613
2634
  (prop_types__WEBPACK_IMPORTED_MODULE_0___default().func),
2614
- prop_types__WEBPACK_IMPORTED_MODULE_0___default().shape({ current: prop_types__WEBPACK_IMPORTED_MODULE_0___default().instanceOf((react__WEBPACK_IMPORTED_MODULE_1___default().Component)) })])
2635
+ // eslint-disable-next-line react/forbid-prop-types
2636
+ prop_types__WEBPACK_IMPORTED_MODULE_0___default().shape({ current: (prop_types__WEBPACK_IMPORTED_MODULE_0___default().object) })])
2615
2637
 
2616
2638
  };
2617
2639
  withOnyx.defaultProps = {