react-native-onyx 1.0.109 → 1.0.111

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.
@@ -2384,7 +2384,10 @@ const provider = {
2384
2384
  * @param {String} key
2385
2385
  * @return {Promise<*>}
2386
2386
  */
2387
- getItem: (key) => (0,idb_keyval__WEBPACK_IMPORTED_MODULE_0__.get)(key, getCustomStore()),
2387
+ getItem: (key) => (0,idb_keyval__WEBPACK_IMPORTED_MODULE_0__.get)(key, getCustomStore())
2388
+
2389
+ // idb-keyval returns undefined for missing items, but this needs to return null so that idb-keyval does the same thing as SQLiteStorage.
2390
+ .then((val) => val === undefined ? null : val),
2388
2391
 
2389
2392
  /**
2390
2393
  * Remove given key and it's value from storage
@@ -2584,6 +2587,10 @@ function _extends() {_extends = Object.assign ? Object.assign.bind() : function
2584
2587
 
2585
2588
 
2586
2589
 
2590
+ // This is a list of keys that can exist on a `mapping`, but are not directly related to loading data from Onyx. When the keys of a mapping are looped over to check
2591
+ // if a key has changed, it's a good idea to skip looking at these properties since they would have unexpected results.
2592
+ const mappingPropertiesToIgnoreChangesTo = ['initialValue'];
2593
+
2587
2594
  /**
2588
2595
  * Returns the display name of a component
2589
2596
  *
@@ -2668,27 +2675,52 @@ const getOnyxDataFromState = (state, onyxToStateMapping) => underscore__WEBPACK_
2668
2675
  }
2669
2676
 
2670
2677
  componentDidMount() {
2678
+ const onyxDataFromState = getOnyxDataFromState(this.state, mapOnyxToState);
2679
+
2671
2680
  // Subscribe each of the state properties to the proper Onyx key
2672
2681
  underscore__WEBPACK_IMPORTED_MODULE_2___default().each(mapOnyxToState, (mapping, propertyName) => {
2673
- this.connectMappingToOnyx(mapping, propertyName);
2682
+ if (underscore__WEBPACK_IMPORTED_MODULE_2___default().includes(mappingPropertiesToIgnoreChangesTo, propertyName)) {
2683
+ return;
2684
+ }
2685
+ const key = _Str__WEBPACK_IMPORTED_MODULE_3__.result(mapping.key, { ...this.props, ...onyxDataFromState });
2686
+ this.connectMappingToOnyx(mapping, propertyName, key);
2674
2687
  });
2675
2688
  this.checkEvictableKeys();
2676
2689
  }
2677
2690
 
2678
- componentDidUpdate() {
2679
- // When the state is passed to the key functions with Str.result(), omit anything
2680
- // from state that was not part of the mapped keys.
2691
+ componentDidUpdate(prevProps, prevState) {
2692
+ // The whole purpose of this method is to check to see if a key that is subscribed to Onyx has changed, and then Onyx needs to be disconnected from the old
2693
+ // key and connected to the new key.
2694
+ // For example, a key could change if KeyB depends on data loading from Onyx for KeyA.
2695
+ const isFirstTimeUpdatingAfterLoading = prevState.loading && !this.state.loading;
2681
2696
  const onyxDataFromState = getOnyxDataFromState(this.state, mapOnyxToState);
2697
+ const prevOnyxDataFromState = getOnyxDataFromState(prevState, mapOnyxToState);
2698
+
2699
+ // This ensures that only one property is reconnecting at a time, or else it can lead to race conditions and infinite rendering loops. No fun!
2700
+ let isReconnectingToOnyx = false;
2682
2701
 
2683
- // If any of the mappings use data from the props, then when the props change, all the
2684
- // connections need to be reconnected with the new props
2685
2702
  underscore__WEBPACK_IMPORTED_MODULE_2___default().each(mapOnyxToState, (mapping, propName) => {
2686
- const previousKey = mapping.previousKey;
2703
+ // Some properties can be ignored and also return early if the component is already reconnecting to Onyx
2704
+ if (underscore__WEBPACK_IMPORTED_MODULE_2___default().includes(mappingPropertiesToIgnoreChangesTo, propName) || isReconnectingToOnyx) {
2705
+ return;
2706
+ }
2707
+
2708
+ // The previous key comes from either:
2709
+ // 1) The initial key that was connected to (ie. set from `componentDidMount()`)
2710
+ // 2) The updated props which caused `componentDidUpdate()` to run
2711
+ // The first case cannot be used all the time because of race conditions where `componentDidUpdate()` can be triggered before connectingMappingToOnyx() is done
2712
+ // (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.
2713
+ // 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,
2714
+ // 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.
2715
+ const previousKey = isFirstTimeUpdatingAfterLoading ?
2716
+ mapping.previousKey :
2717
+ _Str__WEBPACK_IMPORTED_MODULE_3__.result(mapping.key, { ...prevProps, ...prevOnyxDataFromState });
2687
2718
  const newKey = _Str__WEBPACK_IMPORTED_MODULE_3__.result(mapping.key, { ...this.props, ...onyxDataFromState });
2688
2719
  if (previousKey !== newKey) {
2720
+ isReconnectingToOnyx = true;
2689
2721
  _Onyx__WEBPACK_IMPORTED_MODULE_4__["default"].disconnect(this.activeConnectionIDs[previousKey], previousKey);
2690
2722
  delete this.activeConnectionIDs[previousKey];
2691
- this.connectMappingToOnyx(mapping, propName);
2723
+ this.connectMappingToOnyx(mapping, propName, newKey);
2692
2724
  }
2693
2725
  });
2694
2726
  this.checkEvictableKeys();
@@ -2828,16 +2860,13 @@ const getOnyxDataFromState = (state, onyxToStateMapping) => underscore__WEBPACK_
2828
2860
  * @param {string} statePropertyName the name of the state property that Onyx will add the data to
2829
2861
  * @param {boolean} [mapping.initWithStoredValues] If set to false, then no data will be prefilled into the
2830
2862
  * component
2863
+ * @param {string} key to connect to Onyx with
2831
2864
  */
2832
- connectMappingToOnyx(mapping, statePropertyName) {
2833
- const key = _Str__WEBPACK_IMPORTED_MODULE_3__.result(mapping.key, { ...this.props, ...getOnyxDataFromState(this.state, mapOnyxToState) });
2834
-
2835
- // Remember the previous key so that if it ever changes, the component will reconnect to Onyx
2836
- // in componentDidUpdate
2837
- if (statePropertyName !== 'initialValue' && mapOnyxToState[statePropertyName]) {
2838
- // eslint-disable-next-line no-param-reassign
2839
- mapOnyxToState[statePropertyName].previousKey = key;
2840
- }
2865
+ connectMappingToOnyx(mapping, statePropertyName, key) {
2866
+ // Remember what the previous key was so that key changes can be detected when data is being loaded from Onyx. This will allow
2867
+ // dependent keys to finish loading their data.
2868
+ // eslint-disable-next-line no-param-reassign
2869
+ mapOnyxToState[statePropertyName].previousKey = key;
2841
2870
 
2842
2871
  // eslint-disable-next-line rulesdir/prefer-onyx-connect-in-libs
2843
2872
  this.activeConnectionIDs[key] = _Onyx__WEBPACK_IMPORTED_MODULE_4__["default"].connect({