@@ -510,6 +510,14 @@ const ComboBox = forwardRef(
510510 const prevSelectedItemProp = useRef < ItemType | null | undefined > (
511511 selectedItemProp
512512 ) ;
513+ const isSyncingControlledSelectionRef = useRef ( false ) ;
514+ const pendingControlledSelectionRef = useRef < {
515+ pending : boolean ;
516+ value : ItemType | null | undefined ;
517+ } > ( {
518+ pending : false ,
519+ value : undefined ,
520+ } ) ;
513521
514522 useEffect ( ( ) => {
515523 isManualClearingRef . current = isClearing ;
@@ -523,6 +531,10 @@ const ComboBox = forwardRef(
523531 // fully controlled combobox: handle changes to selectedItemProp
524532 useEffect ( ( ) => {
525533 if ( prevSelectedItemProp . current !== selectedItemProp ) {
534+ pendingControlledSelectionRef . current = {
535+ pending : true ,
536+ value : selectedItemProp ,
537+ } ;
526538 const currentInputValue = getInputValue ( {
527539 initialSelectedItem,
528540 itemToString,
@@ -885,13 +897,17 @@ const ComboBox = forwardRef(
885897 isItemDisabled : isDisabledItem ,
886898 ...downshiftProps ,
887899 onStateChange : ( { type, selectedItem : newSelectedItem } ) => {
900+ if (
901+ isManualClearingRef . current ||
902+ isSyncingControlledSelectionRef . current
903+ ) {
904+ isSyncingControlledSelectionRef . current = false ;
905+ return ;
906+ }
888907 downshiftProps ?. onStateChange ?.( {
889908 type,
890909 selectedItem : newSelectedItem ,
891910 } ) ;
892- if ( isManualClearingRef . current ) {
893- return ;
894- }
895911 if (
896912 ( type === ItemClick ||
897913 type === FunctionSelectItem ||
@@ -914,6 +930,19 @@ const ComboBox = forwardRef(
914930 const currentSelectedItem =
915931 typeof selectedItemProp !== 'undefined' ? selectedItemProp : selectedItem ;
916932
933+ useEffect ( ( ) => {
934+ if ( pendingControlledSelectionRef . current . pending ) {
935+ const { value } = pendingControlledSelectionRef . current ;
936+ const nextSelectedItem = typeof value === 'undefined' ? null : value ;
937+ pendingControlledSelectionRef . current . pending = false ;
938+
939+ if ( ! isEqual ( selectedItem , nextSelectedItem ) ) {
940+ isSyncingControlledSelectionRef . current = true ;
941+ selectItem ( nextSelectedItem ) ;
942+ }
943+ }
944+ } , [ selectedItem , selectedItemProp , selectItem ] ) ;
945+
917946 useEffect ( ( ) => {
918947 // Used to expose the downshift actions to consumers for use with downshiftProps
919948 // An odd pattern, here we mutate the value stored in the ref provided from the consumer.
0 commit comments