Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion src/BaseSelect/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -362,7 +362,7 @@ const BaseSelect = React.forwardRef<BaseSelectRef, BaseSelectProps>((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,
Expand Down Expand Up @@ -647,6 +647,7 @@ const BaseSelect = React.forwardRef<BaseSelectRef, BaseSelectProps>((props, ref)
showScrollBar,
styles,
classNames,
lockOptions,
}),
[
props,
Expand All @@ -659,6 +660,7 @@ const BaseSelect = React.forwardRef<BaseSelectRef, BaseSelectProps>((props, ref)
showScrollBar,
styles,
classNames,
lockOptions,
],
);

Expand Down
5 changes: 3 additions & 2 deletions src/OptionList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ const OptionList: React.ForwardRefRenderFunction<RefOptionListProps, {}> = (_, r
notFoundContent,
onPopupScroll,
showScrollBar,
lockOptions,
} = useBaseProps();
const {
maxCount,
Expand All @@ -68,8 +69,8 @@ const OptionList: React.ForwardRefRenderFunction<RefOptionListProps, {}> = (_, r

const memoFlattenOptions = useMemo(
() => flattenOptions,
[open, flattenOptions],
(prev, next) => next[0] && prev[1] !== next[1],
[open, lockOptions],
(prev, next) => next[0] && !next[1],
);
Comment on lines 70 to 74

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

critical

这个 useMemo 的实现似乎会破坏搜索过滤功能。当前的逻辑是当下拉框打开且未锁定时(open && !lockOptions),memoFlattenOptions 将不会更新。这会导致用户在搜索时,选项列表不会刷新。

为了解决这个问题,同时保留修复闪烁的逻辑,我们可以修改 useMemo 的依赖和比较函数。我们希望仅在 lockOptionstrue 时“冻结”选项列表,或者在 flattenOptions 没有实际变化时避免不必要的重算。

以下是一个建议的修改,它能正确处理过滤和锁定:

  const memoFlattenOptions = useMemo(
    () => flattenOptions,
    [lockOptions, flattenOptions],
    (prev, next) => next[0] || prev[1] === next[1],
  );


// =========================== List ===========================
Expand Down
1 change: 1 addition & 0 deletions src/hooks/useBaseProps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ export interface BaseSelectContextProps extends BaseSelectProps {
triggerOpen: boolean;
multiple: boolean;
toggleOpen: (open?: boolean) => void;
lockOptions: boolean;
}

export const BaseSelectContext = React.createContext<BaseSelectContextProps>(null);
Expand Down
10 changes: 8 additions & 2 deletions src/hooks/useOpen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand All @@ -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);
Expand All @@ -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 (
Expand All @@ -82,6 +87,7 @@ export default function useOpen(
!cancelFun?.()
) {
triggerEvent(nextOpenVal);
setLock(false);
}
}

Expand All @@ -95,5 +101,5 @@ export default function useOpen(
}
});

return [mergedOpen, toggleOpen] as const;
return [mergedOpen, toggleOpen, lock];
}
Loading