react-native-onyx 1.0.120 → 1.0.121

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/lib/utils.js CHANGED
@@ -1,12 +1,7 @@
1
1
  import _ from 'underscore';
2
2
 
3
3
  function areObjectsEmpty(a, b) {
4
- return (
5
- typeof a === 'object'
6
- && typeof b === 'object'
7
- && _.isEmpty(a)
8
- && _.isEmpty(b)
9
- );
4
+ return typeof a === 'object' && typeof b === 'object' && _.isEmpty(a) && _.isEmpty(b);
10
5
  }
11
6
 
12
7
  // Mostly copied from https://medium.com/@lubaka.a/how-to-remove-lodash-performance-improvement-b306669ad0e1
@@ -14,22 +9,24 @@ function areObjectsEmpty(a, b) {
14
9
  /**
15
10
  * @param {mixed} val
16
11
  * @returns {boolean}
17
- */
12
+ */
18
13
  function isMergeableObject(val) {
19
14
  const nonNullObject = val != null ? typeof val === 'object' : false;
20
- return (nonNullObject
21
- && Object.prototype.toString.call(val) !== '[object RegExp]'
22
- && Object.prototype.toString.call(val) !== '[object Date]')
15
+ return (
16
+ nonNullObject &&
17
+ Object.prototype.toString.call(val) !== '[object RegExp]' &&
18
+ Object.prototype.toString.call(val) !== '[object Date]' &&
23
19
  // eslint-disable-next-line rulesdir/prefer-underscore-method
24
- && !Array.isArray(val);
20
+ !Array.isArray(val)
21
+ );
25
22
  }
26
23
 
27
24
  /**
28
- * @param {Object} target
29
- * @param {Object} source
30
- * @param {Boolean} shouldRemoveNullObjectValues
31
- * @returns {Object}
32
- */
25
+ * @param {Object} target
26
+ * @param {Object} source
27
+ * @param {Boolean} shouldRemoveNullObjectValues
28
+ * @returns {Object}
29
+ */
33
30
  function mergeObject(target, source, shouldRemoveNullObjectValues = true) {
34
31
  const destination = {};
35
32
  if (isMergeableObject(target)) {
@@ -65,7 +62,7 @@ function mergeObject(target, source, shouldRemoveNullObjectValues = true) {
65
62
  const isSourceKeyMergable = isMergeableObject(source[key]);
66
63
 
67
64
  if (isSourceKeyMergable && target[key]) {
68
- if ((!shouldRemoveNullObjectValues || isSourceKeyMergable)) {
65
+ if (!shouldRemoveNullObjectValues || isSourceKeyMergable) {
69
66
  // eslint-disable-next-line no-use-before-define
70
67
  destination[key] = fastMerge(target[key], source[key], shouldRemoveNullObjectValues);
71
68
  }
@@ -85,11 +82,11 @@ function mergeObject(target, source, shouldRemoveNullObjectValues = true) {
85
82
  * On native, when merging an existing value with new changes, SQLite will use JSON_PATCH, which removes top-level nullish values.
86
83
  * To be consistent with the behaviour for merge, we'll also want to remove null values for "set" operations.
87
84
  *
88
- * @param {Object|Array} target
89
- * @param {Object|Array} source
90
- * @param {Boolean} shouldRemoveNullObjectValues
91
- * @returns {Object|Array}
92
- */
85
+ * @param {Object|Array} target
86
+ * @param {Object|Array} source
87
+ * @param {Boolean} shouldRemoveNullObjectValues
88
+ * @returns {Object|Array}
89
+ */
93
90
  function fastMerge(target, source, shouldRemoveNullObjectValues = true) {
94
91
  // We have to ignore arrays and nullish values here,
95
92
  // otherwise "mergeObject" will throw an error,
package/lib/withOnyx.d.ts CHANGED
@@ -40,13 +40,7 @@ type EntryBaseMapping<TOnyxKey extends OnyxKey> = {
40
40
  * },
41
41
  * ```
42
42
  */
43
- type BaseMappingKey<
44
- TComponentProps,
45
- TOnyxProps,
46
- TOnyxProp extends keyof TOnyxProps,
47
- TOnyxKey extends OnyxKey,
48
- TOnyxValue
49
- > = IsEqual<TOnyxValue, TOnyxProps[TOnyxProp]> extends true
43
+ type BaseMappingKey<TComponentProps, TOnyxProps, TOnyxProp extends keyof TOnyxProps, TOnyxKey extends OnyxKey, TOnyxValue> = IsEqual<TOnyxValue, TOnyxProps[TOnyxProp]> extends true
50
44
  ? {
51
45
  key: TOnyxKey | ((props: Omit<TComponentProps, keyof TOnyxProps>) => TOnyxKey);
52
46
  }
@@ -67,12 +61,7 @@ type BaseMappingKey<
67
61
  * },
68
62
  * ```
69
63
  */
70
- type BaseMappingStringKeyAndSelector<
71
- TComponentProps,
72
- TOnyxProps,
73
- TOnyxProp extends keyof TOnyxProps,
74
- TOnyxKey extends OnyxKey
75
- > = {
64
+ type BaseMappingStringKeyAndSelector<TComponentProps, TOnyxProps, TOnyxProp extends keyof TOnyxProps, TOnyxKey extends OnyxKey> = {
76
65
  key: TOnyxKey;
77
66
  selector: Selector<TOnyxKey, TOnyxProps[TOnyxProp]>;
78
67
  };
@@ -92,12 +81,7 @@ type BaseMappingStringKeyAndSelector<
92
81
  * },
93
82
  * ```
94
83
  */
95
- type BaseMappingFunctionKeyAndSelector<
96
- TComponentProps,
97
- TOnyxProps,
98
- TOnyxProp extends keyof TOnyxProps,
99
- TOnyxKey extends OnyxKey
100
- > = {
84
+ type BaseMappingFunctionKeyAndSelector<TComponentProps, TOnyxProps, TOnyxProp extends keyof TOnyxProps, TOnyxKey extends OnyxKey> = {
101
85
  key: (props: Omit<TComponentProps, keyof TOnyxProps>) => TOnyxKey;
102
86
  selector: Selector<TOnyxKey, TOnyxProps[TOnyxProp]>;
103
87
  };
@@ -105,10 +89,8 @@ type BaseMappingFunctionKeyAndSelector<
105
89
  /**
106
90
  * Represents the mapping options between an Onyx key and the component's prop with all its possibilities.
107
91
  */
108
- type Mapping<TComponentProps, TOnyxProps, TOnyxProp extends keyof TOnyxProps, TOnyxKey extends OnyxKey> = BaseMapping<
109
- TComponentProps,
110
- TOnyxProps
111
- > & EntryBaseMapping<TOnyxKey> &
92
+ type Mapping<TComponentProps, TOnyxProps, TOnyxProp extends keyof TOnyxProps, TOnyxKey extends OnyxKey> = BaseMapping<TComponentProps, TOnyxProps> &
93
+ EntryBaseMapping<TOnyxKey> &
112
94
  (
113
95
  | BaseMappingKey<TComponentProps, TOnyxProps, TOnyxProp, TOnyxKey, OnyxEntry<KeyValueMapping[TOnyxKey]>>
114
96
  | BaseMappingStringKeyAndSelector<TComponentProps, TOnyxProps, TOnyxProp, TOnyxKey>
@@ -118,12 +100,8 @@ type Mapping<TComponentProps, TOnyxProps, TOnyxProp extends keyof TOnyxProps, TO
118
100
  /**
119
101
  * Represents the mapping options between an Onyx collection key without suffix and the component's prop with all its possibilities.
120
102
  */
121
- type CollectionMapping<
122
- TComponentProps,
123
- TOnyxProps,
124
- TOnyxProp extends keyof TOnyxProps,
125
- TOnyxKey extends CollectionKeyBase
126
- > = BaseMapping<TComponentProps, TOnyxProps> & CollectionBaseMapping<TOnyxKey> &
103
+ type CollectionMapping<TComponentProps, TOnyxProps, TOnyxProp extends keyof TOnyxProps, TOnyxKey extends CollectionKeyBase> = BaseMapping<TComponentProps, TOnyxProps> &
104
+ CollectionBaseMapping<TOnyxKey> &
127
105
  (
128
106
  | BaseMappingKey<TComponentProps, TOnyxProps, TOnyxProp, TOnyxKey, OnyxCollection<KeyValueMapping[TOnyxKey]>>
129
107
  | BaseMappingStringKeyAndSelector<TComponentProps, TOnyxProps, TOnyxProp, TOnyxKey>
@@ -153,9 +131,7 @@ type OnyxPropCollectionMapping<TComponentProps, TOnyxProps, TOnyxProp extends ke
153
131
  */
154
132
  declare function withOnyx<TComponentProps, TOnyxProps>(
155
133
  mapping: {
156
- [TOnyxProp in keyof TOnyxProps]:
157
- | OnyxPropMapping<TComponentProps, TOnyxProps, TOnyxProp>
158
- | OnyxPropCollectionMapping<TComponentProps, TOnyxProps, TOnyxProp>;
134
+ [TOnyxProp in keyof TOnyxProps]: OnyxPropMapping<TComponentProps, TOnyxProps, TOnyxProp> | OnyxPropCollectionMapping<TComponentProps, TOnyxProps, TOnyxProp>;
159
135
  },
160
136
  shouldDelayUpdates?: boolean,
161
137
  ): (component: React.ComponentType<TComponentProps>) => React.ComponentType<Omit<TComponentProps, keyof TOnyxProps>>;
package/lib/withOnyx.js CHANGED
@@ -36,7 +36,7 @@ const getOnyxDataFromState = (state, onyxToStateMapping) => _.pick(state, _.keys
36
36
  export default function (mapOnyxToState, shouldDelayUpdates = false) {
37
37
  // A list of keys that must be present in tempState before we can render the WrappedComponent
38
38
  const requiredKeysForInit = _.chain(mapOnyxToState)
39
- .omit(config => config.initWithStoredValues === false)
39
+ .omit((config) => config.initWithStoredValues === false)
40
40
  .keys()
41
41
  .value();
42
42
  return (WrappedComponent) => {
@@ -74,11 +74,7 @@ export default function (mapOnyxToState, shouldDelayUpdates = false) {
74
74
  * In reality, Onyx.merge() will only update the subscriber after all merges have been batched and the previous value is retrieved via a get() (returns a promise).
75
75
  * So, we won't use the cache optimization here as it will lead us to arbitrarily defer various actions in the application code.
76
76
  */
77
- if (
78
- (value !== undefined
79
- && !Onyx.hasPendingMergeForKey(key))
80
- || mapping.allowStaleData
81
- ) {
77
+ if ((value !== undefined && !Onyx.hasPendingMergeForKey(key)) || mapping.allowStaleData) {
82
78
  // eslint-disable-next-line no-param-reassign
83
79
  resultObj[propertyName] = value;
84
80
  }
@@ -132,9 +128,7 @@ export default function (mapOnyxToState, shouldDelayUpdates = false) {
132
128
  // (eg. if a user switches chats really quickly). In this case, it's much more stable to always look at the changes to prevProp and prevState to derive the key.
133
129
  // The second case cannot be used all the time because the onyx data doesn't change the first time that `componentDidUpdate()` runs after loading. In this case,
134
130
  // the `mapping.previousKey` must be used for the comparison or else this logic never detects that onyx data could have changed during the loading process.
135
- const previousKey = isFirstTimeUpdatingAfterLoading
136
- ? mapping.previousKey
137
- : Str.result(mapping.key, {...prevProps, ...prevOnyxDataFromState});
131
+ const previousKey = isFirstTimeUpdatingAfterLoading ? mapping.previousKey : Str.result(mapping.key, {...prevProps, ...prevOnyxDataFromState});
138
132
  const newKey = Str.result(mapping.key, {...this.props, ...onyxDataFromState});
139
133
  if (previousKey !== newKey) {
140
134
  Onyx.disconnect(this.activeConnectionIDs[previousKey], previousKey);
@@ -202,7 +196,7 @@ export default function (mapOnyxToState, shouldDelayUpdates = false) {
202
196
  this.tempState[statePropertyName] = val;
203
197
 
204
198
  // If some key does not have a value yet, do not update the state yet
205
- const tempStateIsMissingKey = _.some(requiredKeysForInit, key => _.isUndefined(this.tempState[key]));
199
+ const tempStateIsMissingKey = _.some(requiredKeysForInit, (key) => _.isUndefined(this.tempState[key]));
206
200
  if (tempStateIsMissingKey) {
207
201
  return;
208
202
  }
@@ -212,29 +206,33 @@ export default function (mapOnyxToState, shouldDelayUpdates = false) {
212
206
 
213
207
  // Full of hacky workarounds to prevent the race condition described above.
214
208
  this.setState((prevState) => {
215
- const finalState = _.reduce(stateUpdate, (result, value, key) => {
216
- if (key === 'loading') {
209
+ const finalState = _.reduce(
210
+ stateUpdate,
211
+ (result, value, key) => {
212
+ if (key === 'loading') {
213
+ return result;
214
+ }
215
+
216
+ const initialValue = mapOnyxToState[key].initialValue;
217
+
218
+ // If initialValue is there and the state contains something different it means
219
+ // an update has already been received and we can discard the value we are trying to hydrate
220
+ if (!_.isUndefined(initialValue) && !_.isUndefined(prevState[key]) && prevState[key] !== initialValue) {
221
+ // eslint-disable-next-line no-param-reassign
222
+ result[key] = prevState[key];
223
+
224
+ // if value is already there (without initial value) then we can discard the value we are trying to hydrate
225
+ } else if (!_.isUndefined(prevState[key])) {
226
+ // eslint-disable-next-line no-param-reassign
227
+ result[key] = prevState[key];
228
+ } else {
229
+ // eslint-disable-next-line no-param-reassign
230
+ result[key] = value;
231
+ }
217
232
  return result;
218
- }
219
-
220
- const initialValue = mapOnyxToState[key].initialValue;
221
-
222
- // If initialValue is there and the state contains something different it means
223
- // an update has already been received and we can discard the value we are trying to hydrate
224
- if (!_.isUndefined(initialValue) && !_.isUndefined(prevState[key]) && prevState[key] !== initialValue) {
225
- // eslint-disable-next-line no-param-reassign
226
- result[key] = prevState[key];
227
-
228
- // if value is already there (without initial value) then we can discard the value we are trying to hydrate
229
- } else if (!_.isUndefined(prevState[key])) {
230
- // eslint-disable-next-line no-param-reassign
231
- result[key] = prevState[key];
232
- } else {
233
- // eslint-disable-next-line no-param-reassign
234
- result[key] = value;
235
- }
236
- return result;
237
- }, {});
233
+ },
234
+ {},
235
+ );
238
236
 
239
237
  finalState.loading = false;
240
238
  return finalState;
@@ -350,8 +348,13 @@ export default function (mapOnyxToState, shouldDelayUpdates = false) {
350
348
  withOnyx.displayName = `withOnyx(${displayName})`;
351
349
  return React.forwardRef((props, ref) => {
352
350
  const Component = withOnyx;
353
- // eslint-disable-next-line react/jsx-props-no-spreading
354
- return <Component {...props} forwardedRef={ref} />;
351
+ return (
352
+ <Component
353
+ // eslint-disable-next-line react/jsx-props-no-spreading
354
+ {...props}
355
+ forwardedRef={ref}
356
+ />
357
+ );
355
358
  });
356
359
  };
357
360
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-onyx",
3
- "version": "1.0.120",
3
+ "version": "1.0.121",
4
4
  "author": "Expensify, Inc.",
5
5
  "homepage": "https://expensify.com",
6
6
  "description": "State management for React Native",
@@ -40,7 +40,8 @@
40
40
  "build:docs": "node buildDocs.js",
41
41
  "e2e": "playwright test",
42
42
  "e2e-ui": "playwright test --ui",
43
- "postinstall": "cd tests/e2e/app && npm install"
43
+ "postinstall": "cd tests/e2e/app && npm install",
44
+ "prettier": "prettier --write ."
44
45
  },
45
46
  "dependencies": {
46
47
  "ascii-table": "0.0.9",
@@ -61,7 +62,8 @@
61
62
  "babel-jest": "^26.2.2",
62
63
  "babel-loader": "^8.2.5",
63
64
  "eslint": "^7.6.0",
64
- "eslint-config-expensify": "^2.0.38",
65
+ "eslint-config-expensify": "^2.0.42",
66
+ "eslint-config-prettier": "^8.8.0",
65
67
  "eslint-plugin-jsx-a11y": "^6.6.1",
66
68
  "eslint-plugin-react": "^7.31.10",
67
69
  "idb-keyval": "^6.2.1",
@@ -69,6 +71,7 @@
69
71
  "jest-cli": "^26.5.2",
70
72
  "jsdoc-to-markdown": "^7.1.0",
71
73
  "metro-react-native-babel-preset": "^0.72.3",
74
+ "prettier": "^2.8.8",
72
75
  "prop-types": "^15.7.2",
73
76
  "react": "18.2.0",
74
77
  "react-dom": "^18.2.0",