From 9a1b732a0e0a0fa9f99b1e75acb21a7acc51b4ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BA=8C=E8=B4=A7=E6=9C=BA=E5=99=A8=E4=BA=BA?= Date: Tue, 21 Oct 2025 23:57:27 +0800 Subject: [PATCH] chore: adjust open order --- src/BaseSelect/index.tsx | 8 ++++++-- src/hooks/useOpen.ts | 36 +++++++++++++++++++++++------------- 2 files changed, 29 insertions(+), 15 deletions(-) diff --git a/src/BaseSelect/index.tsx b/src/BaseSelect/index.tsx index f093559a..96e2e47e 100644 --- a/src/BaseSelect/index.tsx +++ b/src/BaseSelect/index.tsx @@ -570,7 +570,9 @@ const BaseSelect = React.forwardRef((props, ref) } if (!disabled) { - triggerOpen(false); + triggerOpen(false, { + lazy: true, + }); onBlur?.(event); } }; @@ -582,7 +584,9 @@ const BaseSelect = React.forwardRef((props, ref) // We should give focus back to selector if clicked item is not focusable if (popupElement?.contains(target as HTMLElement) && triggerOpen) { // Tell `open` not to close since it's safe in the popup - triggerOpen(true, true); + triggerOpen(true, { + ignoreNext: true, + }); } onMouseDown?.(event, ...restArgs); diff --git a/src/hooks/useOpen.ts b/src/hooks/useOpen.ts index 8b4e6004..2347675f 100644 --- a/src/hooks/useOpen.ts +++ b/src/hooks/useOpen.ts @@ -22,7 +22,13 @@ const macroTask = (fn: VoidFunction, times = 1) => { * Trigger by latest open call, if nextOpen is undefined, means toggle. * ignoreNext will skip next call in the macro task queue. */ -export type TriggerOpenType = (nextOpen?: boolean, ignoreNext?: boolean) => void; +export type TriggerOpenType = ( + nextOpen?: boolean, + config?: { + ignoreNext?: boolean; + lazy?: boolean; + }, +) => void; /** * When `open` is controlled, follow the controlled value; @@ -61,30 +67,34 @@ export default function useOpen( internalSetOpen(nextOpen); }); - const toggleOpen = useEvent((nextOpen?: boolean, ignoreNext = false) => { + const toggleOpen = useEvent((nextOpen, config = {}) => { + const { ignoreNext = false, lazy = false } = config; + taskIdRef.current += 1; const id = taskIdRef.current; const nextOpenVal = typeof nextOpen === 'boolean' ? nextOpen : !mergedOpen; // Since `mergedOpen` is post-processed, we need to check if the value really changed - if (nextOpenVal) { - triggerEvent(true); - - // Lock if needed - if (ignoreNext) { - taskLockRef.current = ignoreNext; - - macroTask(() => { - taskLockRef.current = false; - }, 2); + if (nextOpenVal || !lazy) { + if (!taskLockRef.current) { + triggerEvent(nextOpenVal); + + // Lock if needed + if (ignoreNext) { + taskLockRef.current = ignoreNext; + + macroTask(() => { + taskLockRef.current = false; + }, 2); + } } return; } macroTask(() => { if (id === taskIdRef.current && !taskLockRef.current) { - triggerEvent(false); + triggerEvent(nextOpenVal); } }); });