downshift 8.2.3 → 8.2.4-alpha.0

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/README.md CHANGED
@@ -1460,7 +1460,7 @@ MIT
1460
1460
  [npm]: https://www.npmjs.com/
1461
1461
  [node]: https://nodejs.org
1462
1462
  [build-badge]:
1463
- https://img.shields.io/github/workflow/status/downshift-js/downshift/validate?logo=github&style=flat-square
1463
+ https://img.shields.io/github/actions/workflow/status/downshift-js/downshift/validate.yml?branch=master&logo=github&style=flat-square
1464
1464
  [build]:
1465
1465
  https://github.com/downshift-js/downshift/actions?query=workflow%3Avalidate+branch%3Amaster
1466
1466
  [coverage-badge]:
@@ -1697,9 +1697,10 @@ function useLatestRef(val) {
1697
1697
  * @param {Function} reducer Reducer function from downshift.
1698
1698
  * @param {Object} props The hook props, also passed to createInitialState.
1699
1699
  * @param {Function} createInitialState Function that returns the initial state.
1700
+ * @param {Function} isStateEqual Function that checks if a previous state is equal to the next.
1700
1701
  * @returns {Array} An array with the state and an action dispatcher.
1701
1702
  */
1702
- function useEnhancedReducer(reducer, props, createInitialState) {
1703
+ function useEnhancedReducer(reducer, props, createInitialState, isStateEqual) {
1703
1704
  var prevStateRef = React.useRef();
1704
1705
  var actionRef = React.useRef();
1705
1706
  var enhancedReducer = React.useCallback(function (state, action) {
@@ -1722,11 +1723,19 @@ function useEnhancedReducer(reducer, props, createInitialState) {
1722
1723
  }, [propsRef]);
1723
1724
  var action = actionRef.current;
1724
1725
  React.useEffect(function () {
1725
- if (action && prevStateRef.current && prevStateRef.current !== state) {
1726
+ console.log('effect');
1727
+ var shouldCallOnChangeProps = action && prevStateRef.current && !isStateEqual(prevStateRef.current, state);
1728
+ console.log('passed', prevStateRef.current, state);
1729
+ if (shouldCallOnChangeProps) {
1726
1730
  callOnChangeProps(action, getState(prevStateRef.current, action.props), state);
1727
1731
  }
1728
1732
  prevStateRef.current = state;
1729
- }, [state, props, action]);
1733
+ }, [state, action, isStateEqual]);
1734
+ React.useEffect(function () {
1735
+ if (props) {
1736
+ prevStateRef.current = getState(prevStateRef.current, props);
1737
+ }
1738
+ }, [props]);
1730
1739
  return [state, dispatchWithProps];
1731
1740
  }
1732
1741
 
@@ -1737,10 +1746,11 @@ function useEnhancedReducer(reducer, props, createInitialState) {
1737
1746
  * @param {Function} reducer Reducer function from downshift.
1738
1747
  * @param {Object} props The hook props, also passed to createInitialState.
1739
1748
  * @param {Function} createInitialState Function that returns the initial state.
1749
+ * @param {Function} isStateEqual Function that checks if a previous state is equal to the next.
1740
1750
  * @returns {Array} An array with the state and an action dispatcher.
1741
1751
  */
1742
- function useControlledReducer$1(reducer, props, createInitialState) {
1743
- var _useEnhancedReducer = useEnhancedReducer(reducer, props, createInitialState),
1752
+ function useControlledReducer$1(reducer, props, createInitialState, isStateEqual) {
1753
+ var _useEnhancedReducer = useEnhancedReducer(reducer, props, createInitialState, isStateEqual),
1744
1754
  state = _useEnhancedReducer[0],
1745
1755
  dispatch = _useEnhancedReducer[1];
1746
1756
  return [getState(state, props), dispatch];
@@ -2022,6 +2032,18 @@ function getChangesOnSelection(props, highlightedIndex, inputValue) {
2022
2032
  }));
2023
2033
  }
2024
2034
 
2035
+ /**
2036
+ * Check if a state is equal for dropdowns, by comparing isOpen, inputValue, highlightedIndex and selected item.
2037
+ * Used by useSelect and useCombobox.
2038
+ *
2039
+ * @param {Object} prevState
2040
+ * @param {Object} newState
2041
+ * @returns {boolean} Wheather the states are deeply equal.
2042
+ */
2043
+ function isDropdownsStateEqual(prevState, newState) {
2044
+ return prevState.isOpen === newState.isOpen && prevState.inputValue === newState.inputValue && prevState.highlightedIndex === newState.highlightedIndex && prevState.selectedItem === newState.selectedItem;
2045
+ }
2046
+
2025
2047
  // Shared between all exports.
2026
2048
  var commonPropTypes = {
2027
2049
  environment: PropTypes__default["default"].shape({
@@ -2344,14 +2366,13 @@ function useSelect(userProps) {
2344
2366
  getA11ySelectionMessage = props.getA11ySelectionMessage,
2345
2367
  getA11yStatusMessage = props.getA11yStatusMessage;
2346
2368
  // Initial state depending on controlled props.
2347
- var _useControlledReducer = useControlledReducer$1(downshiftSelectReducer, props, getInitialState$2),
2369
+ var _useControlledReducer = useControlledReducer$1(downshiftSelectReducer, props, getInitialState$2, isDropdownsStateEqual),
2348
2370
  state = _useControlledReducer[0],
2349
2371
  dispatch = _useControlledReducer[1];
2350
2372
  var isOpen = state.isOpen,
2351
2373
  highlightedIndex = state.highlightedIndex,
2352
2374
  selectedItem = state.selectedItem,
2353
2375
  inputValue = state.inputValue;
2354
-
2355
2376
  // Element efs.
2356
2377
  var toggleButtonRef = React.useRef(null);
2357
2378
  var menuRef = React.useRef(null);
@@ -2829,11 +2850,12 @@ var propTypes$1 = _extends__default["default"]({}, commonDropdownPropTypes, {
2829
2850
  * @param {Function} reducer Reducer function from downshift.
2830
2851
  * @param {Object} props The hook props, also passed to createInitialState.
2831
2852
  * @param {Function} createInitialState Function that returns the initial state.
2853
+ * @param {Function} isStateEqual Function that checks if a previous state is equal to the next.
2832
2854
  * @returns {Array} An array with the state and an action dispatcher.
2833
2855
  */
2834
- function useControlledReducer(reducer, props, createInitialState) {
2856
+ function useControlledReducer(reducer, props, createInitialState, isStateEqual) {
2835
2857
  var previousSelectedItemRef = React.useRef();
2836
- var _useEnhancedReducer = useEnhancedReducer(reducer, props, createInitialState),
2858
+ var _useEnhancedReducer = useEnhancedReducer(reducer, props, createInitialState, isStateEqual),
2837
2859
  state = _useEnhancedReducer[0],
2838
2860
  dispatch = _useEnhancedReducer[1];
2839
2861
 
@@ -3007,7 +3029,7 @@ function useCombobox(userProps) {
3007
3029
  getA11ySelectionMessage = props.getA11ySelectionMessage,
3008
3030
  itemToString = props.itemToString;
3009
3031
  // Initial state depending on controlled props.
3010
- var _useControlledReducer = useControlledReducer(downshiftUseComboboxReducer, props, getInitialState$1),
3032
+ var _useControlledReducer = useControlledReducer(downshiftUseComboboxReducer, props, getInitialState$1, isDropdownsStateEqual),
3011
3033
  state = _useControlledReducer[0],
3012
3034
  dispatch = _useControlledReducer[1];
3013
3035
  var isOpen = state.isOpen,
@@ -3492,6 +3514,18 @@ function getA11yRemovalMessage(selectionParameters) {
3492
3514
  itemToStringLocal = selectionParameters.itemToString;
3493
3515
  return itemToStringLocal(removedSelectedItem) + " has been removed.";
3494
3516
  }
3517
+
3518
+ /**
3519
+ * Check if a state is equal for taglist, by comparing active index and selected items.
3520
+ * Used by useSelect and useCombobox.
3521
+ *
3522
+ * @param {Object} prevState
3523
+ * @param {Object} newState
3524
+ * @returns {boolean} Wheather the states are deeply equal.
3525
+ */
3526
+ function isStateEqual(prevState, newState) {
3527
+ return prevState.selectedItems === newState.selectedItems && prevState.activeIndex === newState.activeIndex;
3528
+ }
3495
3529
  var propTypes = _extends__default["default"]({}, commonPropTypes, {
3496
3530
  selectedItems: PropTypes__default["default"].array,
3497
3531
  initialSelectedItems: PropTypes__default["default"].array,
@@ -3681,7 +3715,7 @@ function useMultipleSelection(userProps) {
3681
3715
  keyNavigationPrevious = props.keyNavigationPrevious;
3682
3716
 
3683
3717
  // Reducer init.
3684
- var _useControlledReducer = useControlledReducer$1(downshiftMultipleSelectionReducer, props, getInitialState),
3718
+ var _useControlledReducer = useControlledReducer$1(downshiftMultipleSelectionReducer, props, getInitialState, isStateEqual),
3685
3719
  state = _useControlledReducer[0],
3686
3720
  dispatch = _useControlledReducer[1];
3687
3721
  var activeIndex = state.activeIndex,
@@ -1684,9 +1684,10 @@ function useLatestRef(val) {
1684
1684
  * @param {Function} reducer Reducer function from downshift.
1685
1685
  * @param {Object} props The hook props, also passed to createInitialState.
1686
1686
  * @param {Function} createInitialState Function that returns the initial state.
1687
+ * @param {Function} isStateEqual Function that checks if a previous state is equal to the next.
1687
1688
  * @returns {Array} An array with the state and an action dispatcher.
1688
1689
  */
1689
- function useEnhancedReducer(reducer, props, createInitialState) {
1690
+ function useEnhancedReducer(reducer, props, createInitialState, isStateEqual) {
1690
1691
  var prevStateRef = useRef();
1691
1692
  var actionRef = useRef();
1692
1693
  var enhancedReducer = useCallback(function (state, action) {
@@ -1709,11 +1710,19 @@ function useEnhancedReducer(reducer, props, createInitialState) {
1709
1710
  }, [propsRef]);
1710
1711
  var action = actionRef.current;
1711
1712
  useEffect(function () {
1712
- if (action && prevStateRef.current && prevStateRef.current !== state) {
1713
+ console.log('effect');
1714
+ var shouldCallOnChangeProps = action && prevStateRef.current && !isStateEqual(prevStateRef.current, state);
1715
+ console.log('passed', prevStateRef.current, state);
1716
+ if (shouldCallOnChangeProps) {
1713
1717
  callOnChangeProps(action, getState(prevStateRef.current, action.props), state);
1714
1718
  }
1715
1719
  prevStateRef.current = state;
1716
- }, [state, props, action]);
1720
+ }, [state, action, isStateEqual]);
1721
+ useEffect(function () {
1722
+ if (props) {
1723
+ prevStateRef.current = getState(prevStateRef.current, props);
1724
+ }
1725
+ }, [props]);
1717
1726
  return [state, dispatchWithProps];
1718
1727
  }
1719
1728
 
@@ -1724,10 +1733,11 @@ function useEnhancedReducer(reducer, props, createInitialState) {
1724
1733
  * @param {Function} reducer Reducer function from downshift.
1725
1734
  * @param {Object} props The hook props, also passed to createInitialState.
1726
1735
  * @param {Function} createInitialState Function that returns the initial state.
1736
+ * @param {Function} isStateEqual Function that checks if a previous state is equal to the next.
1727
1737
  * @returns {Array} An array with the state and an action dispatcher.
1728
1738
  */
1729
- function useControlledReducer$1(reducer, props, createInitialState) {
1730
- var _useEnhancedReducer = useEnhancedReducer(reducer, props, createInitialState),
1739
+ function useControlledReducer$1(reducer, props, createInitialState, isStateEqual) {
1740
+ var _useEnhancedReducer = useEnhancedReducer(reducer, props, createInitialState, isStateEqual),
1731
1741
  state = _useEnhancedReducer[0],
1732
1742
  dispatch = _useEnhancedReducer[1];
1733
1743
  return [getState(state, props), dispatch];
@@ -2009,6 +2019,18 @@ function getChangesOnSelection(props, highlightedIndex, inputValue) {
2009
2019
  }));
2010
2020
  }
2011
2021
 
2022
+ /**
2023
+ * Check if a state is equal for dropdowns, by comparing isOpen, inputValue, highlightedIndex and selected item.
2024
+ * Used by useSelect and useCombobox.
2025
+ *
2026
+ * @param {Object} prevState
2027
+ * @param {Object} newState
2028
+ * @returns {boolean} Wheather the states are deeply equal.
2029
+ */
2030
+ function isDropdownsStateEqual(prevState, newState) {
2031
+ return prevState.isOpen === newState.isOpen && prevState.inputValue === newState.inputValue && prevState.highlightedIndex === newState.highlightedIndex && prevState.selectedItem === newState.selectedItem;
2032
+ }
2033
+
2012
2034
  // Shared between all exports.
2013
2035
  var commonPropTypes = {
2014
2036
  environment: PropTypes.shape({
@@ -2331,14 +2353,13 @@ function useSelect(userProps) {
2331
2353
  getA11ySelectionMessage = props.getA11ySelectionMessage,
2332
2354
  getA11yStatusMessage = props.getA11yStatusMessage;
2333
2355
  // Initial state depending on controlled props.
2334
- var _useControlledReducer = useControlledReducer$1(downshiftSelectReducer, props, getInitialState$2),
2356
+ var _useControlledReducer = useControlledReducer$1(downshiftSelectReducer, props, getInitialState$2, isDropdownsStateEqual),
2335
2357
  state = _useControlledReducer[0],
2336
2358
  dispatch = _useControlledReducer[1];
2337
2359
  var isOpen = state.isOpen,
2338
2360
  highlightedIndex = state.highlightedIndex,
2339
2361
  selectedItem = state.selectedItem,
2340
2362
  inputValue = state.inputValue;
2341
-
2342
2363
  // Element efs.
2343
2364
  var toggleButtonRef = useRef(null);
2344
2365
  var menuRef = useRef(null);
@@ -2816,11 +2837,12 @@ var propTypes$1 = _extends({}, commonDropdownPropTypes, {
2816
2837
  * @param {Function} reducer Reducer function from downshift.
2817
2838
  * @param {Object} props The hook props, also passed to createInitialState.
2818
2839
  * @param {Function} createInitialState Function that returns the initial state.
2840
+ * @param {Function} isStateEqual Function that checks if a previous state is equal to the next.
2819
2841
  * @returns {Array} An array with the state and an action dispatcher.
2820
2842
  */
2821
- function useControlledReducer(reducer, props, createInitialState) {
2843
+ function useControlledReducer(reducer, props, createInitialState, isStateEqual) {
2822
2844
  var previousSelectedItemRef = useRef();
2823
- var _useEnhancedReducer = useEnhancedReducer(reducer, props, createInitialState),
2845
+ var _useEnhancedReducer = useEnhancedReducer(reducer, props, createInitialState, isStateEqual),
2824
2846
  state = _useEnhancedReducer[0],
2825
2847
  dispatch = _useEnhancedReducer[1];
2826
2848
 
@@ -2994,7 +3016,7 @@ function useCombobox(userProps) {
2994
3016
  getA11ySelectionMessage = props.getA11ySelectionMessage,
2995
3017
  itemToString = props.itemToString;
2996
3018
  // Initial state depending on controlled props.
2997
- var _useControlledReducer = useControlledReducer(downshiftUseComboboxReducer, props, getInitialState$1),
3019
+ var _useControlledReducer = useControlledReducer(downshiftUseComboboxReducer, props, getInitialState$1, isDropdownsStateEqual),
2998
3020
  state = _useControlledReducer[0],
2999
3021
  dispatch = _useControlledReducer[1];
3000
3022
  var isOpen = state.isOpen,
@@ -3479,6 +3501,18 @@ function getA11yRemovalMessage(selectionParameters) {
3479
3501
  itemToStringLocal = selectionParameters.itemToString;
3480
3502
  return itemToStringLocal(removedSelectedItem) + " has been removed.";
3481
3503
  }
3504
+
3505
+ /**
3506
+ * Check if a state is equal for taglist, by comparing active index and selected items.
3507
+ * Used by useSelect and useCombobox.
3508
+ *
3509
+ * @param {Object} prevState
3510
+ * @param {Object} newState
3511
+ * @returns {boolean} Wheather the states are deeply equal.
3512
+ */
3513
+ function isStateEqual(prevState, newState) {
3514
+ return prevState.selectedItems === newState.selectedItems && prevState.activeIndex === newState.activeIndex;
3515
+ }
3482
3516
  var propTypes = _extends({}, commonPropTypes, {
3483
3517
  selectedItems: PropTypes.array,
3484
3518
  initialSelectedItems: PropTypes.array,
@@ -3668,7 +3702,7 @@ function useMultipleSelection(userProps) {
3668
3702
  keyNavigationPrevious = props.keyNavigationPrevious;
3669
3703
 
3670
3704
  // Reducer init.
3671
- var _useControlledReducer = useControlledReducer$1(downshiftMultipleSelectionReducer, props, getInitialState),
3705
+ var _useControlledReducer = useControlledReducer$1(downshiftMultipleSelectionReducer, props, getInitialState, isStateEqual),
3672
3706
  state = _useControlledReducer[0],
3673
3707
  dispatch = _useControlledReducer[1];
3674
3708
  var activeIndex = state.activeIndex,
@@ -1593,9 +1593,10 @@ function useLatestRef(val) {
1593
1593
  * @param {Function} reducer Reducer function from downshift.
1594
1594
  * @param {Object} props The hook props, also passed to createInitialState.
1595
1595
  * @param {Function} createInitialState Function that returns the initial state.
1596
+ * @param {Function} isStateEqual Function that checks if a previous state is equal to the next.
1596
1597
  * @returns {Array} An array with the state and an action dispatcher.
1597
1598
  */
1598
- function useEnhancedReducer(reducer, props, createInitialState) {
1599
+ function useEnhancedReducer(reducer, props, createInitialState, isStateEqual) {
1599
1600
  var prevStateRef = React.useRef();
1600
1601
  var actionRef = React.useRef();
1601
1602
  var enhancedReducer = React.useCallback(function (state, action) {
@@ -1618,11 +1619,19 @@ function useEnhancedReducer(reducer, props, createInitialState) {
1618
1619
  }, [propsRef]);
1619
1620
  var action = actionRef.current;
1620
1621
  React.useEffect(function () {
1621
- if (action && prevStateRef.current && prevStateRef.current !== state) {
1622
+ console.log('effect');
1623
+ var shouldCallOnChangeProps = action && prevStateRef.current && !isStateEqual(prevStateRef.current, state);
1624
+ console.log('passed', prevStateRef.current, state);
1625
+ if (shouldCallOnChangeProps) {
1622
1626
  callOnChangeProps(action, getState(prevStateRef.current, action.props), state);
1623
1627
  }
1624
1628
  prevStateRef.current = state;
1625
- }, [state, props, action]);
1629
+ }, [state, action, isStateEqual]);
1630
+ React.useEffect(function () {
1631
+ if (props) {
1632
+ prevStateRef.current = getState(prevStateRef.current, props);
1633
+ }
1634
+ }, [props]);
1626
1635
  return [state, dispatchWithProps];
1627
1636
  }
1628
1637
 
@@ -1633,10 +1642,11 @@ function useEnhancedReducer(reducer, props, createInitialState) {
1633
1642
  * @param {Function} reducer Reducer function from downshift.
1634
1643
  * @param {Object} props The hook props, also passed to createInitialState.
1635
1644
  * @param {Function} createInitialState Function that returns the initial state.
1645
+ * @param {Function} isStateEqual Function that checks if a previous state is equal to the next.
1636
1646
  * @returns {Array} An array with the state and an action dispatcher.
1637
1647
  */
1638
- function useControlledReducer$1(reducer, props, createInitialState) {
1639
- var _useEnhancedReducer = useEnhancedReducer(reducer, props, createInitialState),
1648
+ function useControlledReducer$1(reducer, props, createInitialState, isStateEqual) {
1649
+ var _useEnhancedReducer = useEnhancedReducer(reducer, props, createInitialState, isStateEqual),
1640
1650
  state = _useEnhancedReducer[0],
1641
1651
  dispatch = _useEnhancedReducer[1];
1642
1652
  return [getState(state, props), dispatch];
@@ -1877,6 +1887,18 @@ function getChangesOnSelection(props, highlightedIndex, inputValue) {
1877
1887
  }));
1878
1888
  }
1879
1889
 
1890
+ /**
1891
+ * Check if a state is equal for dropdowns, by comparing isOpen, inputValue, highlightedIndex and selected item.
1892
+ * Used by useSelect and useCombobox.
1893
+ *
1894
+ * @param {Object} prevState
1895
+ * @param {Object} newState
1896
+ * @returns {boolean} Wheather the states are deeply equal.
1897
+ */
1898
+ function isDropdownsStateEqual(prevState, newState) {
1899
+ return prevState.isOpen === newState.isOpen && prevState.inputValue === newState.inputValue && prevState.highlightedIndex === newState.highlightedIndex && prevState.selectedItem === newState.selectedItem;
1900
+ }
1901
+
1880
1902
  // Shared between all exports.
1881
1903
  var commonPropTypes = {
1882
1904
  environment: PropTypes__default["default"].shape({
@@ -2199,14 +2221,13 @@ function useSelect(userProps) {
2199
2221
  getA11ySelectionMessage = props.getA11ySelectionMessage,
2200
2222
  getA11yStatusMessage = props.getA11yStatusMessage;
2201
2223
  // Initial state depending on controlled props.
2202
- var _useControlledReducer = useControlledReducer$1(downshiftSelectReducer, props, getInitialState$2),
2224
+ var _useControlledReducer = useControlledReducer$1(downshiftSelectReducer, props, getInitialState$2, isDropdownsStateEqual),
2203
2225
  state = _useControlledReducer[0],
2204
2226
  dispatch = _useControlledReducer[1];
2205
2227
  var isOpen = state.isOpen,
2206
2228
  highlightedIndex = state.highlightedIndex,
2207
2229
  selectedItem = state.selectedItem,
2208
2230
  inputValue = state.inputValue;
2209
-
2210
2231
  // Element efs.
2211
2232
  var toggleButtonRef = React.useRef(null);
2212
2233
  var menuRef = React.useRef(null);
@@ -2668,11 +2689,12 @@ var propTypes$1 = _extends__default["default"]({}, commonDropdownPropTypes, {
2668
2689
  * @param {Function} reducer Reducer function from downshift.
2669
2690
  * @param {Object} props The hook props, also passed to createInitialState.
2670
2691
  * @param {Function} createInitialState Function that returns the initial state.
2692
+ * @param {Function} isStateEqual Function that checks if a previous state is equal to the next.
2671
2693
  * @returns {Array} An array with the state and an action dispatcher.
2672
2694
  */
2673
- function useControlledReducer(reducer, props, createInitialState) {
2695
+ function useControlledReducer(reducer, props, createInitialState, isStateEqual) {
2674
2696
  var previousSelectedItemRef = React.useRef();
2675
- var _useEnhancedReducer = useEnhancedReducer(reducer, props, createInitialState),
2697
+ var _useEnhancedReducer = useEnhancedReducer(reducer, props, createInitialState, isStateEqual),
2676
2698
  state = _useEnhancedReducer[0],
2677
2699
  dispatch = _useEnhancedReducer[1];
2678
2700
 
@@ -2846,7 +2868,7 @@ function useCombobox(userProps) {
2846
2868
  getA11ySelectionMessage = props.getA11ySelectionMessage,
2847
2869
  itemToString = props.itemToString;
2848
2870
  // Initial state depending on controlled props.
2849
- var _useControlledReducer = useControlledReducer(downshiftUseComboboxReducer, props, getInitialState$1),
2871
+ var _useControlledReducer = useControlledReducer(downshiftUseComboboxReducer, props, getInitialState$1, isDropdownsStateEqual),
2850
2872
  state = _useControlledReducer[0],
2851
2873
  dispatch = _useControlledReducer[1];
2852
2874
  var isOpen = state.isOpen,
@@ -3338,6 +3360,18 @@ function getA11yRemovalMessage(selectionParameters) {
3338
3360
  itemToStringLocal = selectionParameters.itemToString;
3339
3361
  return itemToStringLocal(removedSelectedItem) + " has been removed.";
3340
3362
  }
3363
+
3364
+ /**
3365
+ * Check if a state is equal for taglist, by comparing active index and selected items.
3366
+ * Used by useSelect and useCombobox.
3367
+ *
3368
+ * @param {Object} prevState
3369
+ * @param {Object} newState
3370
+ * @returns {boolean} Wheather the states are deeply equal.
3371
+ */
3372
+ function isStateEqual(prevState, newState) {
3373
+ return prevState.selectedItems === newState.selectedItems && prevState.activeIndex === newState.activeIndex;
3374
+ }
3341
3375
  var propTypes = _extends__default["default"]({}, commonPropTypes, {
3342
3376
  selectedItems: PropTypes__default["default"].array,
3343
3377
  initialSelectedItems: PropTypes__default["default"].array,
@@ -3527,7 +3561,7 @@ function useMultipleSelection(userProps) {
3527
3561
  keyNavigationPrevious = props.keyNavigationPrevious;
3528
3562
 
3529
3563
  // Reducer init.
3530
- var _useControlledReducer = useControlledReducer$1(downshiftMultipleSelectionReducer, props, getInitialState),
3564
+ var _useControlledReducer = useControlledReducer$1(downshiftMultipleSelectionReducer, props, getInitialState, isStateEqual),
3531
3565
  state = _useControlledReducer[0],
3532
3566
  dispatch = _useControlledReducer[1];
3533
3567
  var activeIndex = state.activeIndex,
@@ -1692,9 +1692,10 @@ function useLatestRef(val) {
1692
1692
  * @param {Function} reducer Reducer function from downshift.
1693
1693
  * @param {Object} props The hook props, also passed to createInitialState.
1694
1694
  * @param {Function} createInitialState Function that returns the initial state.
1695
+ * @param {Function} isStateEqual Function that checks if a previous state is equal to the next.
1695
1696
  * @returns {Array} An array with the state and an action dispatcher.
1696
1697
  */
1697
- function useEnhancedReducer(reducer, props, createInitialState) {
1698
+ function useEnhancedReducer(reducer, props, createInitialState, isStateEqual) {
1698
1699
  var prevStateRef = React.useRef();
1699
1700
  var actionRef = React.useRef();
1700
1701
  var enhancedReducer = React.useCallback(function (state, action) {
@@ -1717,11 +1718,19 @@ function useEnhancedReducer(reducer, props, createInitialState) {
1717
1718
  }, [propsRef]);
1718
1719
  var action = actionRef.current;
1719
1720
  React.useEffect(function () {
1720
- if (action && prevStateRef.current && prevStateRef.current !== state) {
1721
+ console.log('effect');
1722
+ var shouldCallOnChangeProps = action && prevStateRef.current && !isStateEqual(prevStateRef.current, state);
1723
+ console.log('passed', prevStateRef.current, state);
1724
+ if (shouldCallOnChangeProps) {
1721
1725
  callOnChangeProps(action, getState(prevStateRef.current, action.props), state);
1722
1726
  }
1723
1727
  prevStateRef.current = state;
1724
- }, [state, props, action]);
1728
+ }, [state, action, isStateEqual]);
1729
+ React.useEffect(function () {
1730
+ if (props) {
1731
+ prevStateRef.current = getState(prevStateRef.current, props);
1732
+ }
1733
+ }, [props]);
1725
1734
  return [state, dispatchWithProps];
1726
1735
  }
1727
1736
 
@@ -1732,10 +1741,11 @@ function useEnhancedReducer(reducer, props, createInitialState) {
1732
1741
  * @param {Function} reducer Reducer function from downshift.
1733
1742
  * @param {Object} props The hook props, also passed to createInitialState.
1734
1743
  * @param {Function} createInitialState Function that returns the initial state.
1744
+ * @param {Function} isStateEqual Function that checks if a previous state is equal to the next.
1735
1745
  * @returns {Array} An array with the state and an action dispatcher.
1736
1746
  */
1737
- function useControlledReducer$1(reducer, props, createInitialState) {
1738
- var _useEnhancedReducer = useEnhancedReducer(reducer, props, createInitialState),
1747
+ function useControlledReducer$1(reducer, props, createInitialState, isStateEqual) {
1748
+ var _useEnhancedReducer = useEnhancedReducer(reducer, props, createInitialState, isStateEqual),
1739
1749
  state = _useEnhancedReducer[0],
1740
1750
  dispatch = _useEnhancedReducer[1];
1741
1751
  return [getState(state, props), dispatch];
@@ -2017,6 +2027,18 @@ function getChangesOnSelection(props, highlightedIndex, inputValue) {
2017
2027
  }));
2018
2028
  }
2019
2029
 
2030
+ /**
2031
+ * Check if a state is equal for dropdowns, by comparing isOpen, inputValue, highlightedIndex and selected item.
2032
+ * Used by useSelect and useCombobox.
2033
+ *
2034
+ * @param {Object} prevState
2035
+ * @param {Object} newState
2036
+ * @returns {boolean} Wheather the states are deeply equal.
2037
+ */
2038
+ function isDropdownsStateEqual(prevState, newState) {
2039
+ return prevState.isOpen === newState.isOpen && prevState.inputValue === newState.inputValue && prevState.highlightedIndex === newState.highlightedIndex && prevState.selectedItem === newState.selectedItem;
2040
+ }
2041
+
2020
2042
  // Shared between all exports.
2021
2043
  var commonPropTypes = {
2022
2044
  environment: PropTypes__default["default"].shape({
@@ -2339,14 +2361,13 @@ function useSelect(userProps) {
2339
2361
  getA11ySelectionMessage = props.getA11ySelectionMessage,
2340
2362
  getA11yStatusMessage = props.getA11yStatusMessage;
2341
2363
  // Initial state depending on controlled props.
2342
- var _useControlledReducer = useControlledReducer$1(downshiftSelectReducer, props, getInitialState$2),
2364
+ var _useControlledReducer = useControlledReducer$1(downshiftSelectReducer, props, getInitialState$2, isDropdownsStateEqual),
2343
2365
  state = _useControlledReducer[0],
2344
2366
  dispatch = _useControlledReducer[1];
2345
2367
  var isOpen = state.isOpen,
2346
2368
  highlightedIndex = state.highlightedIndex,
2347
2369
  selectedItem = state.selectedItem,
2348
2370
  inputValue = state.inputValue;
2349
-
2350
2371
  // Element efs.
2351
2372
  var toggleButtonRef = React.useRef(null);
2352
2373
  var menuRef = React.useRef(null);
@@ -2812,11 +2833,12 @@ var propTypes$1 = _extends__default["default"]({}, commonDropdownPropTypes, {
2812
2833
  * @param {Function} reducer Reducer function from downshift.
2813
2834
  * @param {Object} props The hook props, also passed to createInitialState.
2814
2835
  * @param {Function} createInitialState Function that returns the initial state.
2836
+ * @param {Function} isStateEqual Function that checks if a previous state is equal to the next.
2815
2837
  * @returns {Array} An array with the state and an action dispatcher.
2816
2838
  */
2817
- function useControlledReducer(reducer, props, createInitialState) {
2839
+ function useControlledReducer(reducer, props, createInitialState, isStateEqual) {
2818
2840
  var previousSelectedItemRef = React.useRef();
2819
- var _useEnhancedReducer = useEnhancedReducer(reducer, props, createInitialState),
2841
+ var _useEnhancedReducer = useEnhancedReducer(reducer, props, createInitialState, isStateEqual),
2820
2842
  state = _useEnhancedReducer[0],
2821
2843
  dispatch = _useEnhancedReducer[1];
2822
2844
 
@@ -2990,7 +3012,7 @@ function useCombobox(userProps) {
2990
3012
  getA11ySelectionMessage = props.getA11ySelectionMessage,
2991
3013
  itemToString = props.itemToString;
2992
3014
  // Initial state depending on controlled props.
2993
- var _useControlledReducer = useControlledReducer(downshiftUseComboboxReducer, props, getInitialState$1),
3015
+ var _useControlledReducer = useControlledReducer(downshiftUseComboboxReducer, props, getInitialState$1, isDropdownsStateEqual),
2994
3016
  state = _useControlledReducer[0],
2995
3017
  dispatch = _useControlledReducer[1];
2996
3018
  var isOpen = state.isOpen,
@@ -3475,6 +3497,18 @@ function getA11yRemovalMessage(selectionParameters) {
3475
3497
  itemToStringLocal = selectionParameters.itemToString;
3476
3498
  return itemToStringLocal(removedSelectedItem) + " has been removed.";
3477
3499
  }
3500
+
3501
+ /**
3502
+ * Check if a state is equal for taglist, by comparing active index and selected items.
3503
+ * Used by useSelect and useCombobox.
3504
+ *
3505
+ * @param {Object} prevState
3506
+ * @param {Object} newState
3507
+ * @returns {boolean} Wheather the states are deeply equal.
3508
+ */
3509
+ function isStateEqual(prevState, newState) {
3510
+ return prevState.selectedItems === newState.selectedItems && prevState.activeIndex === newState.activeIndex;
3511
+ }
3478
3512
  var propTypes = _extends__default["default"]({}, commonPropTypes, {
3479
3513
  selectedItems: PropTypes__default["default"].array,
3480
3514
  initialSelectedItems: PropTypes__default["default"].array,
@@ -3664,7 +3698,7 @@ function useMultipleSelection(userProps) {
3664
3698
  keyNavigationPrevious = props.keyNavigationPrevious;
3665
3699
 
3666
3700
  // Reducer init.
3667
- var _useControlledReducer = useControlledReducer$1(downshiftMultipleSelectionReducer, props, getInitialState),
3701
+ var _useControlledReducer = useControlledReducer$1(downshiftMultipleSelectionReducer, props, getInitialState, isStateEqual),
3668
3702
  state = _useControlledReducer[0],
3669
3703
  dispatch = _useControlledReducer[1];
3670
3704
  var activeIndex = state.activeIndex,