react-native-onyx 1.0.54 → 1.0.55

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.
@@ -932,19 +932,33 @@ function evictStorageAndRetry(error, onyxMethod) {for (var _len = arguments.leng
932
932
  *
933
933
  * @param {String} key
934
934
  * @param {*} value
935
+ * @param {Boolean} hasChanged
935
936
  * @param {String} method
936
937
  */
937
- function broadcastUpdate(key, value, method) {
938
+ function broadcastUpdate(key, value, hasChanged, method) {
938
939
  // Logging properties only since values could be sensitive things we don't want to log
939
940
  _Logger__WEBPACK_IMPORTED_MODULE_6__.logInfo(`${method}() called for key: ${key}${underscore__WEBPACK_IMPORTED_MODULE_2___default().isObject(value) ? ` properties: ${underscore__WEBPACK_IMPORTED_MODULE_2___default().keys(value).join(',')}` : ''}`);
940
941
 
941
942
  // Update subscribers if the cached value has changed, or when the subscriber specifically requires
942
943
  // all updates regardless of value changes (indicated by initWithStoredValues set to false).
943
- const hasChanged = _OnyxCache__WEBPACK_IMPORTED_MODULE_4__["default"].hasValueChanged(key, value);
944
- _OnyxCache__WEBPACK_IMPORTED_MODULE_4__["default"].set(key, value);
944
+ if (hasChanged) {
945
+ _OnyxCache__WEBPACK_IMPORTED_MODULE_4__["default"].set(key, value);
946
+ } else {
947
+ _OnyxCache__WEBPACK_IMPORTED_MODULE_4__["default"].addToAccessedKeys(key);
948
+ }
949
+
945
950
  notifySubscribersOnNextTick(key, value, (subscriber) => hasChanged || subscriber.initWithStoredValues === false);
946
951
  }
947
952
 
953
+ /**
954
+ * @private
955
+ * @param {String} key
956
+ * @returns {Boolean}
957
+ */
958
+ function hasPendingMergeForKey(key) {
959
+ return Boolean(mergeQueue[key]);
960
+ }
961
+
948
962
  /**
949
963
  * Write a value to our store with the given key
950
964
  *
@@ -958,8 +972,19 @@ function set(key, value) {
958
972
  return remove(key);
959
973
  }
960
974
 
975
+ if (hasPendingMergeForKey(key)) {
976
+ _Logger__WEBPACK_IMPORTED_MODULE_6__.logAlert(`Onyx.set() called after Onyx.merge() for key: ${key}. It is recommended to use set() or merge() not both.`);
977
+ }
978
+
979
+ const hasChanged = _OnyxCache__WEBPACK_IMPORTED_MODULE_4__["default"].hasValueChanged(key, value);
980
+
961
981
  // This approach prioritizes fast UI changes without waiting for data to be stored in device storage.
962
- broadcastUpdate(key, value, 'set');
982
+ broadcastUpdate(key, value, hasChanged, 'set');
983
+
984
+ // If the value has not changed, calling Storage.setItem() would be redundant and a waste of performance, so return early instead.
985
+ if (!hasChanged) {
986
+ return Promise.resolve();
987
+ }
963
988
 
964
989
  return _storage__WEBPACK_IMPORTED_MODULE_5__["default"].setItem(key, value).
965
990
  catch((error) => evictStorageAndRetry(error, set, key, value));
@@ -1002,11 +1027,11 @@ function multiSet(data) {
1002
1027
  * Merges an array of changes with an existing value
1003
1028
  *
1004
1029
  * @private
1005
- * @param {Array<*>} changes Array of changes that should be applied to the existing value
1006
1030
  * @param {*} existingValue
1031
+ * @param {Array<*>} changes Array of changes that should be applied to the existing value
1007
1032
  * @returns {*}
1008
1033
  */
1009
- function applyMerge(changes, existingValue) {
1034
+ function applyMerge(existingValue, changes) {
1010
1035
  const lastChange = underscore__WEBPACK_IMPORTED_MODULE_2___default().last(changes);
1011
1036
 
1012
1037
  if (underscore__WEBPACK_IMPORTED_MODULE_2___default().isArray(existingValue) || underscore__WEBPACK_IMPORTED_MODULE_2___default().isArray(lastChange)) {
@@ -1015,14 +1040,10 @@ function applyMerge(changes, existingValue) {
1015
1040
 
1016
1041
  if (underscore__WEBPACK_IMPORTED_MODULE_2___default().isObject(existingValue) || underscore__WEBPACK_IMPORTED_MODULE_2___default().every(changes, (underscore__WEBPACK_IMPORTED_MODULE_2___default().isObject))) {
1017
1042
  // Object values are merged one after the other
1018
- return underscore__WEBPACK_IMPORTED_MODULE_2___default().reduce(changes, (modifiedData, change) => {
1019
- // lodash adds a small overhead so we don't use it here
1020
- // eslint-disable-next-line prefer-object-spread, rulesdir/prefer-underscore-method
1021
- const newData = Object.assign({}, (0,_fastMerge__WEBPACK_IMPORTED_MODULE_9__["default"])(modifiedData, change));
1022
-
1023
- // Remove all first level keys that are explicitly set to null.
1024
- return underscore__WEBPACK_IMPORTED_MODULE_2___default().omit(newData, (value) => underscore__WEBPACK_IMPORTED_MODULE_2___default().isNull(value));
1025
- }, existingValue || {});
1043
+ // lodash adds a small overhead so we don't use it here
1044
+ // eslint-disable-next-line prefer-object-spread, rulesdir/prefer-underscore-method
1045
+ return underscore__WEBPACK_IMPORTED_MODULE_2___default().reduce(changes, (modifiedData, change) => (0,_fastMerge__WEBPACK_IMPORTED_MODULE_9__["default"])(modifiedData, change),
1046
+ existingValue || {});
1026
1047
  }
1027
1048
 
1028
1049
  // If we have anything else we can't merge it so we'll
@@ -1063,17 +1084,30 @@ function merge(key, changes) {
1063
1084
  then((existingValue) => {
1064
1085
  try {
1065
1086
  // 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)
1066
- const batchedChanges = applyMerge(mergeQueue[key]);
1087
+ const batchedChanges = applyMerge(undefined, mergeQueue[key]);
1067
1088
 
1068
1089
  // Clean up the write queue so we
1069
1090
  // don't apply these changes again
1070
1091
  delete mergeQueue[key];
1071
1092
 
1072
1093
  // After that we merge the batched changes with the existing value
1073
- const modifiedData = applyMerge([batchedChanges], existingValue);
1094
+ let modifiedData = applyMerge(existingValue, [batchedChanges]);
1095
+
1096
+ // For objects, the key for null values needs to be removed from the object to ensure the value will get removed from storage completely.
1097
+ // On native, SQLite will remove top-level keys that are null. To be consistent, we remove them on web too.
1098
+ if (!underscore__WEBPACK_IMPORTED_MODULE_2___default().isArray(modifiedData) && underscore__WEBPACK_IMPORTED_MODULE_2___default().isObject(modifiedData)) {
1099
+ modifiedData = underscore__WEBPACK_IMPORTED_MODULE_2___default().omit(modifiedData, (value) => underscore__WEBPACK_IMPORTED_MODULE_2___default().isNull(value));
1100
+ }
1101
+
1102
+ const hasChanged = _OnyxCache__WEBPACK_IMPORTED_MODULE_4__["default"].hasValueChanged(key, modifiedData);
1074
1103
 
1075
1104
  // This approach prioritizes fast UI changes without waiting for data to be stored in device storage.
1076
- broadcastUpdate(key, modifiedData, 'merge');
1105
+ broadcastUpdate(key, modifiedData, hasChanged, 'merge');
1106
+
1107
+ // If the value has not changed, calling Storage.setItem() would be redundant and a waste of performance, so return early instead.
1108
+ if (!hasChanged) {
1109
+ return Promise.resolve();
1110
+ }
1077
1111
 
1078
1112
  return _storage__WEBPACK_IMPORTED_MODULE_5__["default"].mergeItem(key, batchedChanges, modifiedData);
1079
1113
  } catch (error) {
@@ -1084,15 +1118,6 @@ function merge(key, changes) {
1084
1118
  });
1085
1119
  }
1086
1120
 
1087
- /**
1088
- * @private
1089
- * @param {String} key
1090
- * @returns {Boolean}
1091
- */
1092
- function hasPendingMergeForKey(key) {
1093
- return Boolean(mergeQueue[key]);
1094
- }
1095
-
1096
1121
  /**
1097
1122
  * Merge user provided default key value pairs.
1098
1123
  * @private