react-native-onyx 3.0.57 → 3.0.58
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/dist/utils.d.ts +1 -1
- package/dist/utils.js +25 -10
- package/package.json +1 -1
package/dist/utils.d.ts
CHANGED
|
@@ -37,7 +37,7 @@ type FastMergeResult<TValue> = {
|
|
|
37
37
|
declare function fastMerge<TValue>(target: TValue, source: TValue, options?: FastMergeOptions, metadata?: FastMergeMetadata, basePath?: string[]): FastMergeResult<TValue>;
|
|
38
38
|
/** Checks whether the given object is an object and not null/undefined. */
|
|
39
39
|
declare function isEmptyObject<T>(obj: T | EmptyValue): obj is EmptyValue;
|
|
40
|
-
/** Deep removes the nested null values from the given value. */
|
|
40
|
+
/** Deep removes the nested null values from the given value. Returns the original reference if no nulls were found. */
|
|
41
41
|
declare function removeNestedNullValues<TValue extends OnyxInput<OnyxKey> | null>(value: TValue): TValue;
|
|
42
42
|
/** Formats the action name by uppercasing and adding the key if provided. */
|
|
43
43
|
declare function formatActionName(method: string, key?: OnyxKey): string;
|
package/dist/utils.js
CHANGED
|
@@ -39,6 +39,9 @@ function fastMerge(target, source, options, metadata, basePath = []) {
|
|
|
39
39
|
function mergeObject(target, source, options, metadata, basePath) {
|
|
40
40
|
const destination = {};
|
|
41
41
|
const targetObject = isMergeableObject(target) ? target : undefined;
|
|
42
|
+
// Track whether the merge actually changed anything compared to target.
|
|
43
|
+
// If nothing changed, we return the original target reference for reference stability.
|
|
44
|
+
let hasChanged = !targetObject;
|
|
42
45
|
// First we want to copy over all keys from the target into the destination object,
|
|
43
46
|
// in case "target" is a mergable object.
|
|
44
47
|
// If "shouldRemoveNestedNulls" is true, we want to remove null values from the merged object
|
|
@@ -51,6 +54,7 @@ function mergeObject(target, source, options, metadata, basePath) {
|
|
|
51
54
|
// If either the source or target value is null, we want to omit the key from the merged object.
|
|
52
55
|
const shouldOmitNullishProperty = options.shouldRemoveNestedNulls && (targetProperty === null || sourceProperty === null);
|
|
53
56
|
if (targetProperty === undefined || shouldOmitNullishProperty) {
|
|
57
|
+
hasChanged = true;
|
|
54
58
|
continue;
|
|
55
59
|
}
|
|
56
60
|
destination[key] = targetProperty;
|
|
@@ -68,6 +72,9 @@ function mergeObject(target, source, options, metadata, basePath) {
|
|
|
68
72
|
}
|
|
69
73
|
// If the source value is not a mergable object, we need to set the key directly.
|
|
70
74
|
if (!isMergeableObject(sourceProperty)) {
|
|
75
|
+
if (destination[key] !== sourceProperty) {
|
|
76
|
+
hasChanged = true;
|
|
77
|
+
}
|
|
71
78
|
destination[key] = sourceProperty;
|
|
72
79
|
continue;
|
|
73
80
|
}
|
|
@@ -76,6 +83,7 @@ function mergeObject(target, source, options, metadata, basePath) {
|
|
|
76
83
|
// To achieve this, we first mark these nested objects with an internal flag.
|
|
77
84
|
// When calling fastMerge again with "mark" removal mode, the marked objects will be removed.
|
|
78
85
|
if (options.objectRemovalMode === 'mark' && targetProperty === null) {
|
|
86
|
+
hasChanged = true;
|
|
79
87
|
targetProperty = { [ONYX_INTERNALS__REPLACE_OBJECT_MARK]: true };
|
|
80
88
|
metadata.replaceNullPatches.push([[...basePath, key], Object.assign({}, sourceProperty)]);
|
|
81
89
|
}
|
|
@@ -83,6 +91,7 @@ function mergeObject(target, source, options, metadata, basePath) {
|
|
|
83
91
|
// has the internal flag set, we replace the entire destination object with the source one and remove
|
|
84
92
|
// the flag.
|
|
85
93
|
if (options.objectRemovalMode === 'replace' && sourceProperty[ONYX_INTERNALS__REPLACE_OBJECT_MARK]) {
|
|
94
|
+
hasChanged = true;
|
|
86
95
|
// We do a spread here in order to have a new object reference and allow us to delete the internal flag
|
|
87
96
|
// of the merged object only.
|
|
88
97
|
const sourcePropertyWithoutMark = Object.assign({}, sourceProperty);
|
|
@@ -90,9 +99,13 @@ function mergeObject(target, source, options, metadata, basePath) {
|
|
|
90
99
|
destination[key] = sourcePropertyWithoutMark;
|
|
91
100
|
continue;
|
|
92
101
|
}
|
|
93
|
-
|
|
102
|
+
const merged = fastMerge(targetProperty, sourceProperty, options, metadata, [...basePath, key]).result;
|
|
103
|
+
if (merged !== targetProperty) {
|
|
104
|
+
hasChanged = true;
|
|
105
|
+
}
|
|
106
|
+
destination[key] = merged;
|
|
94
107
|
}
|
|
95
|
-
return destination;
|
|
108
|
+
return hasChanged ? destination : targetObject;
|
|
96
109
|
}
|
|
97
110
|
/** Checks whether the given object is an object and not null/undefined. */
|
|
98
111
|
function isEmptyObject(obj) {
|
|
@@ -106,30 +119,32 @@ function isMergeableObject(value) {
|
|
|
106
119
|
const isNonNullObject = value != null ? typeof value === 'object' : false;
|
|
107
120
|
return isNonNullObject && !(value instanceof RegExp) && !(value instanceof Date) && !Array.isArray(value);
|
|
108
121
|
}
|
|
109
|
-
/** Deep removes the nested null values from the given value. */
|
|
122
|
+
/** Deep removes the nested null values from the given value. Returns the original reference if no nulls were found. */
|
|
110
123
|
function removeNestedNullValues(value) {
|
|
111
|
-
if (value === null || value === undefined || typeof value !== 'object') {
|
|
124
|
+
if (value === null || value === undefined || typeof value !== 'object' || Array.isArray(value)) {
|
|
112
125
|
return value;
|
|
113
126
|
}
|
|
114
|
-
|
|
115
|
-
return [...value];
|
|
116
|
-
}
|
|
127
|
+
let hasChanged = false;
|
|
117
128
|
const result = {};
|
|
118
129
|
// eslint-disable-next-line no-restricted-syntax, guard-for-in
|
|
119
130
|
for (const key in value) {
|
|
120
131
|
const propertyValue = value[key];
|
|
121
132
|
if (propertyValue === null || propertyValue === undefined) {
|
|
133
|
+
hasChanged = true;
|
|
122
134
|
continue;
|
|
123
135
|
}
|
|
124
136
|
if (typeof propertyValue === 'object' && !Array.isArray(propertyValue)) {
|
|
125
|
-
const
|
|
126
|
-
|
|
137
|
+
const cleaned = removeNestedNullValues(propertyValue);
|
|
138
|
+
if (cleaned !== propertyValue) {
|
|
139
|
+
hasChanged = true;
|
|
140
|
+
}
|
|
141
|
+
result[key] = cleaned;
|
|
127
142
|
}
|
|
128
143
|
else {
|
|
129
144
|
result[key] = propertyValue;
|
|
130
145
|
}
|
|
131
146
|
}
|
|
132
|
-
return result;
|
|
147
|
+
return hasChanged ? result : value;
|
|
133
148
|
}
|
|
134
149
|
/** Formats the action name by uppercasing and adding the key if provided. */
|
|
135
150
|
function formatActionName(method, key) {
|