diff --git a/src/BaseSelect/index.tsx b/src/BaseSelect/index.tsx index 1c65c250..bfae9a9a 100644 --- a/src/BaseSelect/index.tsx +++ b/src/BaseSelect/index.tsx @@ -362,7 +362,7 @@ const BaseSelect = React.forwardRef((props, ref) // Not trigger `open` when `notFoundContent` is empty const emptyListContent = !notFoundContent && emptyOptions; - const [mergedOpen, triggerOpen] = useOpen( + const [mergedOpen, triggerOpen, lockOptions] = useOpen( defaultOpen || false, open, onPopupVisibleChange, @@ -647,6 +647,7 @@ const BaseSelect = React.forwardRef((props, ref) showScrollBar, styles, classNames, + lockOptions, }), [ props, @@ -659,6 +660,7 @@ const BaseSelect = React.forwardRef((props, ref) showScrollBar, styles, classNames, + lockOptions, ], ); diff --git a/src/OptionList.tsx b/src/OptionList.tsx index c24c19ec..2e954c1d 100644 --- a/src/OptionList.tsx +++ b/src/OptionList.tsx @@ -45,6 +45,7 @@ const OptionList: React.ForwardRefRenderFunction = (_, r notFoundContent, onPopupScroll, showScrollBar, + lockOptions, } = useBaseProps(); const { maxCount, @@ -68,8 +69,8 @@ const OptionList: React.ForwardRefRenderFunction = (_, r const memoFlattenOptions = useMemo( () => flattenOptions, - [open, flattenOptions], - (prev, next) => next[0] && prev[1] !== next[1], + [open, lockOptions], + (prev, next) => next[0] && !next[1], ); // =========================== List =========================== diff --git a/src/hooks/useBaseProps.ts b/src/hooks/useBaseProps.ts index 82715744..569fa8b8 100644 --- a/src/hooks/useBaseProps.ts +++ b/src/hooks/useBaseProps.ts @@ -10,6 +10,7 @@ export interface BaseSelectContextProps extends BaseSelectProps { triggerOpen: boolean; multiple: boolean; toggleOpen: (open?: boolean) => void; + lockOptions: boolean; } export const BaseSelectContext = React.createContext(null); diff --git a/src/hooks/useOpen.ts b/src/hooks/useOpen.ts index 8d248054..2edd547d 100644 --- a/src/hooks/useOpen.ts +++ b/src/hooks/useOpen.ts @@ -43,7 +43,7 @@ export default function useOpen( propOpen: boolean, onOpen: (nextOpen: boolean) => void, postOpen: (nextOpen: boolean) => boolean, -): [boolean, TriggerOpenType] { +): [open: boolean, toggleOpen: TriggerOpenType, lockOptions: boolean] { // SSR not support Portal which means we need delay `open` for the first time render const [rendered, setRendered] = useState(false); @@ -53,6 +53,9 @@ export default function useOpen( const [stateOpen, internalSetOpen] = useControlledState(defaultOpen, propOpen); + // Lock for options update + const [lock, setLock] = useState(false); + // During SSR, always return false for open state const ssrSafeOpen = rendered ? stateOpen : false; const mergedOpen = postOpen(ssrSafeOpen); @@ -70,9 +73,11 @@ export default function useOpen( const { cancelFun } = config; taskIdRef.current += 1; + const id = taskIdRef.current; const nextOpenVal = typeof nextOpen === 'boolean' ? nextOpen : !mergedOpen; + setLock(!nextOpenVal); function triggerUpdate() { if ( @@ -82,6 +87,7 @@ export default function useOpen( !cancelFun?.() ) { triggerEvent(nextOpenVal); + setLock(false); } } @@ -95,5 +101,5 @@ export default function useOpen( } }); - return [mergedOpen, toggleOpen] as const; + return [mergedOpen, toggleOpen, lock]; }