Repository navigation
Select v6 searchValue is removed when options are updated with onSearch #55968
Copy link
Copy link
Closed
Closed
Copy link
Labels
6.x🐛 BugAnt Design Team had proved that this is a bug.Ant Design Team had proved that this is a bug.
Description
Reproduction link
Steps to reproduce
- Create a Select component with showSearch enabled and async options loading
- Use onSearch to trigger an API call (debounced) that updates the options prop
- Type a search query (e.g., "test")
- Wait for the API response to return and update the options
import { useState } from 'react';
import { Select } from 'antd';
import { useQuery, QueryClient, QueryClientProvider } from '@tanstack/react-query';
import debounce from 'lodash-es/debounce';
const queryClient = new QueryClient();
// Simulated API call
const fetchOptions = async (query: string) => {
await new Promise((resolve) => setTimeout(resolve, 500));
return [
{ value: '1', label: `Result 1 for "${query}"` },
{ value: '2', label: `Result 2 for "${query}"` },
];
};
const AsyncSelect = () => {
const [searchTerm, setSearchTerm] = useState('');
const [debouncedSearchTerm, setDebouncedSearchTerm] = useState('');
const { data: options = [], isFetching } = useQuery({
queryKey: ['options', debouncedSearchTerm],
queryFn: () => fetchOptions(debouncedSearchTerm),
enabled: debouncedSearchTerm.length >= 3,
});
const debouncedSetSearch = debounce((value: string) => {
setDebouncedSearchTerm(value);
}, 300);
const handleSearch = (value: string) => {
setSearchTerm(value);
debouncedSetSearch(value);
};
return (
<Select
showSearch
style={{ width: 300 }}
placeholder="Search..."
options={options}
loading={isFetching}
onSearch={handleSearch}
filterOption={false}
/>
);
};
const App = () => (
<QueryClientProvider client={queryClient}>
<AsyncSelect />
</QueryClientProvider>
);
What is expected?
When the user types "John Doe" and the API returns results, the search input should retain the value "test" and display the filtered options below, with the combobox opened.
What is actually happening?
Intermittently, when the options are updated after the API call returns, the search input value is cleared (reset to empty string). This happens inconsistently - sometimes the search value persists correctly, other times it gets wiped out.
The issue appears to be in rc-select's internal state management. When options update and trigger a re-render, onSearch('') is called internally, which clears the search input, hiding the options in consequence.
| Environment | Info |
|---|---|
| antd | 6.0.0 |
| React | 19.2 |
| System | MacOS |
| Browser | Chrome 142.0.7444.176 |
- Intermittent nature: The bug doesn't happen 100% of the time, making it harder to reproduce consistently. It seems related to timing/race conditions between the options update and internal state management.
Root cause investigation: The issue appears to stem from rc-select replacing useMergedState with useControlledState for managing searchValue. The older implementation handled controlled/uncontrolled state more robustly:
// Old (worked correctly):
const [mergedSearchValue, setSearchValue] = useMergedState('', {
value: searchValue !== undefined ? searchValue : inputValue,
postState: (search) => search || '',
});
// New (causes the bug):
const [internalSearchValue, setSearchValue] = useControlledState('', searchValue);
- Workaround: The issue can be worked around by making the search input fully controlled via showSearch={{ searchValue, onSearch }} and guarding against internal empty string resets:
const [searchValue, setSearchValue] = useState('');
const handleSearch = (value: string) => {
// Guard against rc-select internal resets
if (value === '' && searchValue.length > 1) {
return;
}
setSearchValue(value);
};
<Select
showSearch={{ searchValue, onSearch: handleSearch }}
// ...
/>
- Environment: antd v6.x, React 19.x
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
6.x🐛 BugAnt Design Team had proved that this is a bug.Ant Design Team had proved that this is a bug.
Activity
dosubot commentedon Nov 27, 2025
Hi @aFrameEmilio! I'm Dosu and I’m helping the ant-design team.
This is a known limitation in Ant Design v6's Select component when using async options and showSearch. The root cause is the switch from useMergedState to useControlledState in the underlying rc-select package, which can cause searchValue to reset unexpectedly during async option updates due to race conditions between internal state and prop changes. This is especially noticeable when options are updated after an API call triggered by onSearch, leading to intermittent clearing of the search input [source].
The current official guidance is to set showSearch as a boolean and manage search-related props (onSearch, searchValue, autoClearSearchValue) directly on the Select component—not inside showSearch as an object. Using showSearch={{ searchValue, onSearch }} is not officially supported in released versions and may not work as expected [source].
For advanced scenarios like async option loading, the recommended workaround is to fully control searchValue and onSearch yourself, guarding against unwanted resets (for example, by ignoring empty string resets unless you intend to clear the input). Manual state management is currently the best way to ensure consistent behavior [source].
There is an ongoing API redesign in rc-select to unify search-related props into a SearchConfig object (so showSearch can be an object), but this is not yet officially released. Backward compatibility is maintained for now, so continue to use the boolean showSearch and set search-related props directly on Select [source].
If you need more control (e.g., to show searchValue only when focused), you can manage this with onFocus/onBlur handlers and your own state [source].
To reply, just mention @dosu.
Share context across your team and agents. Try Dosu.
zenggpzqbx commentedon Nov 28, 2025
这个主要问题是notFoundContent是null的时候不是有效的节点
MadCcc commentedon Dec 3, 2025
Didn't get reproduced, any more details?
zenggpzqbx commentedon Dec 4, 2025
zenggpzqbx commentedon Dec 4, 2025
github-actions commentedon Dec 20, 2025
@zombieJ 这个 issue 已经超过 14 天没有更新或关联 PR。如果您仍在处理这个 issue,请更新进度;如果您无法继续处理,请联系维护者重新分配。
This issue has been inactive for more than 14 days without any updates or linked PR. If you are still working on this issue, please provide a progress update. If you are unable to continue, please contact the maintainers for reassignment.
andyxmai commentedon Jan 2, 2026
This makes dynamic, remote fetching not usable for
Select. If a user mis-types, the value gets cleared, and they need to start over.kimteayon commentedon Jan 2, 2026
KianChavoshiNejad commentedon Jan 2, 2026
one way I was able to reproduce this is if we pass in something like
loading ? Spin component : null
to the notFoundContent
and change the loading state in the asynchronous function "onSearch" when typing something and the options returned are an empty array it will wipe the users input