refactor(Select): simplify option handling#9648
Conversation
…nality Removed unused filtering functions and optimized the options retrieval logic in the Select component. Updated the SearchSelect component to support enhanced search capabilities with a more flexible showSearch configuration. Adjusted typing for RequestOptionsType to remove boolean from value type. Updated tests to reflect changes in search handling.
…ct component Introduced a new function for options mapping in the Select component, enhancing clarity and performance. Removed unused references and props in the SearchSelect component to simplify its implementation. Adjusted the handling of search functionality for improved user experience.
…earchSelect component Refactored the FieldSelectSearchEdit component to directly use the defaultKeyWords prop for the default search value. Cleaned up the SearchSelect component by removing unnecessary comments and optimizing the focus handling logic.
…n handling Updated the SearchSelect component to improve the handling of search functionality by allowing more flexible user configurations. Introduced destructuring for userConfig to streamline optionFilterProp, onSearch, and searchValue management. Added console logging for options to aid in debugging.
Eliminated the console logging of options in the SearchSelect component to enhance code cleanliness and maintainability.
Eliminated the optionFilterProp from the showSearch configuration in multiple instances of the ProForm component to streamline the search functionality and improve code clarity.
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthrough重构 SearchSelect 的 showSearch 与 options 处理,简化 Select 的 options 源与过滤链路,收窄类型中 value 为仅允许 string|number,并同步调整相关测试与 FieldSelectSearchEdit 的默认关键词传递。 变更Select与SearchSelect选项处理优化
序列图sequenceDiagram
participant User as 用户
participant SearchSelect as SearchSelect 组件
participant FetchData as fetchData 函数
participant OnSearch as showSearch.onSearch
User->>SearchSelect: 输入搜索词
alt fetchDataOnSearch 为 true
SearchSelect->>FetchData: fetchData(value)
FetchData-->>SearchSelect: 返回远程选项数据
end
SearchSelect->>OnSearch: 调用 showSearch.onSearch(value)
User->>SearchSelect: 清空输入或触发 clear
alt showSearch 存在 onSearch
SearchSelect->>OnSearch: showSearch.onSearch('')
else
SearchSelect->>FetchData: fetchData(undefined)
end
User->>SearchSelect: 选择项目
SearchSelect->>FetchData: resetData()
代码审查工作量估计🎯 4 (Complex) | ⏱️ ~45 分钟 诗歌
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Code Review
This pull request refactors the SearchSelect and FieldSelect components to simplify their implementation, removing custom filtering and value-merging logic in favor of delegating to the underlying Ant Design Select component. It also updates typing definitions to restrict option values to strings or numbers and adapts the test suite accordingly. The code review identifies critical issues introduced by this refactoring: removing the searchValue state locks the search input and prevents user interaction, and removing autoClearSearchValue breaks backward compatibility. The reviewer provides suggestions to restore an internal search value state, maintain backward compatibility, and optimize event handlers to prevent duplicate network requests.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
| const { | ||
| mode, | ||
| onSearch, | ||
| onFocus, | ||
| onChange, | ||
| autoClearSearchValue = true, | ||
| searchOnFocus = false, | ||
| resetAfterSelect = false, | ||
| fetchDataOnSearch = true, | ||
| optionFilterProp = 'label', | ||
| optionLabelProp = 'label', | ||
| className, | ||
| disabled, | ||
| options, | ||
| fetchData, | ||
| resetData, | ||
| prefixCls: customizePrefixCls, | ||
| onClear, | ||
| searchValue: propsSearchValue, | ||
| showSearch, | ||
| fieldNames, | ||
| showSearch: _showSearch, | ||
| defaultSearchValue, | ||
| ...restProps | ||
| } = props; |
There was a problem hiding this comment.
By removing the searchValue state, the search input becomes a controlled component locked to the initial defaultSearchValue when it is provided, preventing users from typing or changing the search query.
Additionally, autoClearSearchValue was removed from destructuring, which breaks backward compatibility for top-level autoClearSearchValue configurations.
This suggestion restores the innerSearchValue state and destructures autoClearSearchValue with a default of true to ensure full backward compatibility and correct behavior.
| const { | |
| mode, | |
| onSearch, | |
| onFocus, | |
| onChange, | |
| autoClearSearchValue = true, | |
| searchOnFocus = false, | |
| resetAfterSelect = false, | |
| fetchDataOnSearch = true, | |
| optionFilterProp = 'label', | |
| optionLabelProp = 'label', | |
| className, | |
| disabled, | |
| options, | |
| fetchData, | |
| resetData, | |
| prefixCls: customizePrefixCls, | |
| onClear, | |
| searchValue: propsSearchValue, | |
| showSearch, | |
| fieldNames, | |
| showSearch: _showSearch, | |
| defaultSearchValue, | |
| ...restProps | |
| } = props; | |
| const { | |
| onFocus, | |
| onChange, | |
| searchOnFocus = false, | |
| resetAfterSelect = false, | |
| fetchDataOnSearch = true, | |
| className, | |
| disabled, | |
| options, | |
| fetchData, | |
| resetData, | |
| prefixCls: customizePrefixCls, | |
| onClear, | |
| showSearch: _showSearch, | |
| defaultSearchValue, | |
| autoClearSearchValue = true, | |
| ...restProps | |
| } = props; | |
| const [innerSearchValue, setInnerSearchValue] = React.useState(defaultSearchValue); |
There was a problem hiding this comment.
Actionable comments posted: 3
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
tests/form/base.test.tsx (1)
2010-2017:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winSearchSelect 测试中
onSearch配置请统一到showSearch.onSearch。该用例把
onSearch直接放在fieldProps顶层,但SearchSelect内部是从showSearch对象里读取并包装onSearch回调用于搜索触发;顶层onSearch在该路径下不如showSearch.onSearch一致。建议与其它onSearch用例保持同一写法。🔄 建议一致性修复
fieldProps={{ mode: 'multiple', searchOnFocus: true, - onSearch: (e) => onSearch(e), + showSearch: { + onSearch: (e) => onSearch(e), + }, }}🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@tests/form/base.test.tsx` around lines 2010 - 2017, The test uses ProFormSelect.SearchSelect with onSearch set directly on fieldProps, but SearchSelect expects and wraps the callback from the showSearch object; update the test to move the onSearch handler into fieldProps.showSearch.onSearch (i.e., create or reuse a showSearch object on fieldProps and place the onSearch function there) so the SearchSelect reads and invokes the same handler path as other tests; refer to ProFormSelect.SearchSelect, fieldProps, showSearch, and onSearch when making the change.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/field/components/Select/index.tsx`:
- Around line 107-110: The computed options can be undefined when valueEnum,
fieldProps?.options and request are all absent; update the useMemo for options
(the variable computed with useMemo and getOptionsFormValueEnum) to default to
an empty array instead of undefined so it always matches the SelectOptionType
contract and the now-required SearchSelectProps.options; i.e., ensure the
fallback after evaluating valueEnum and fieldProps?.options returns [].
In `@src/field/components/Select/SearchSelect/index.tsx`:
- Around line 125-139: showSearch 的构建里把 defaultSearchValue 回填到
showSearch.searchValue 会把输入变为受控组件导致锁定,改为不要在 SearchSelect 的内部设置 searchValue;在创建
showSearch(变量 _showSearch / userConfig)时保留 optionFilterProp、onSearch(仍在 onSearch
中调用 fetchData(value) 和 userConfig.onSearch?.(value)),但移除或不赋值 searchValue:
searchValue ?? defaultSearchValue,使默认关键词的初始化留给上游的 defaultKeyWords -> keyWords
链路而不是在 showSearch(或函数 showSearch)内强制控制 input 值。
---
Outside diff comments:
In `@tests/form/base.test.tsx`:
- Around line 2010-2017: The test uses ProFormSelect.SearchSelect with onSearch
set directly on fieldProps, but SearchSelect expects and wraps the callback from
the showSearch object; update the test to move the onSearch handler into
fieldProps.showSearch.onSearch (i.e., create or reuse a showSearch object on
fieldProps and place the onSearch function there) so the SearchSelect reads and
invokes the same handler path as other tests; refer to
ProFormSelect.SearchSelect, fieldProps, showSearch, and onSearch when making the
change.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: aef6368c-703c-4c49-aa7d-08973a4e8a18
📒 Files selected for processing (5)
src/field/components/Select/FieldSelectSearchEdit.tsxsrc/field/components/Select/SearchSelect/index.tsxsrc/field/components/Select/index.tsxsrc/utils/typing.tstests/form/base.test.tsx
… reliability Updated the options retrieval logic in the Select component to default to an empty array when no options are provided, enhancing the robustness of the component. Additionally, removed the defaultSearchValue from the SearchSelect component to streamline its configuration handling.
…ity and remove unused defaultSearchValue Updated the FieldSelectSearchEdit component to rename the defaultKeyWords prop to _defaultKeyWords for improved clarity. Removed the unused defaultSearchValue from the SearchSelect component to streamline its implementation.
|
@coderabbitai review |
✅ Action performedReview finished.
|
Updated the FieldSelectSearchEdit and SearchSelect components to incorporate the request prop for improved data fetching capabilities. Enhanced the options retrieval logic in the Select component to ensure better handling of default keywords and parameters, streamlining the overall configuration process.
There was a problem hiding this comment.
Pull request overview
This PR refactors the Select/SearchSelect implementation to simplify option sourcing and search behavior, and tightens option value typing (string/number only) to improve consistency and maintainability across ProForm Select variants.
Changes:
- Refactors
SearchSelectto centralize search config viashowSearchand simplifyoptionshandling. - Simplifies
useFieldFetchDataoption derivation and request behavior, prioritizing request/valueEnum/fieldProps options. - Updates related tests and type definitions to match the new search/options API.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/form/base.test.tsx | Updates SearchSelect-related tests to use the new showSearch config structure and adjusts related props. |
| src/utils/typing.ts | Tightens option/valueEnum key types to `string |
| src/field/components/Select/SearchSelect/index.tsx | Refactors SearchSelect behavior: new showSearch config handling, onSearch wiring, and simplified options pass-through. |
| src/field/components/Select/index.tsx | Refactors option derivation and request fetching logic in useFieldFetchData. |
| src/field/components/Select/FieldSelectSearchEdit.tsx | Updates FieldSelectSearchEdit to align with the refactored SearchSelect props. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| <Select | ||
| ref={selectRef} | ||
| className={classString} | ||
| allowClear | ||
| autoClearSearchValue={autoClearSearchValue} | ||
| disabled={disabled} | ||
| mode={mode} | ||
| showSearch={showSearch} | ||
| searchValue={searchValue} | ||
| optionFilterProp={optionFilterProp} | ||
| optionLabelProp={optionLabelProp} | ||
| onClear={() => { | ||
| onClear?.(); | ||
| fetchData(undefined); | ||
| if (showSearch) { | ||
| onSearch?.(''); | ||
| setSearchValue(''); | ||
| if (isObject(showSearch) && showSearch.onSearch) { | ||
| showSearch.onSearch(''); | ||
| } else { | ||
| fetchData(undefined); | ||
| } | ||
| }} | ||
| {...restProps} |
| onChange={(value, optionList, ...rest) => { | ||
| // 将搜索框置空 和 antd 行为保持一致 | ||
| if (showSearch && autoClearSearchValue) { | ||
| if (isObject(showSearch) && showSearch.autoClearSearchValue) { | ||
| fetchData(undefined); | ||
| onSearch?.(''); | ||
| setSearchValue(''); | ||
| } else if (showSearch && !autoClearSearchValue) { | ||
| // 当 autoClearSearchValue 为 false 时,保持搜索值不变 | ||
| // 但是需要确保我们的状态与 Ant Design 的内部状态同步 | ||
| // 在 multiple 模式下,Ant Design 可能会自动清除搜索值,我们需要重新设置它 | ||
| if (mode === 'multiple') { | ||
| // 在 multiple 模式下,即使 autoClearSearchValue 为 false, | ||
| // Ant Design 仍可能会清除搜索值,这是正常行为 | ||
| // 我们不需要做任何特殊处理,让 Ant Design 自然处理 | ||
| } | ||
| } | ||
|
|
||
| if (!props.labelInValue) { | ||
| onChange?.(value, optionList, ...rest); | ||
| return; | ||
| } | ||
|
|
||
| if (mode !== 'multiple' && !Array.isArray(optionList)) { | ||
| // 单选情况且用户选择了选项 | ||
| let dataItem = optionList && optionList['data-item']; | ||
|
|
||
| // 如果 dataItem 不存在,尝试从 options 中查找对应的原始数据 | ||
| let foundDataItem = dataItem; | ||
| if (!foundDataItem && value && options) { | ||
| const optionValue = value[valuePropsName] ?? value.value; | ||
| const findDataItem = (opts: RequestOptionsType[]): any => { | ||
| for (const opt of opts) { | ||
| const optValue = opt[valuePropsName] ?? opt.value; | ||
| if (optValue === optionValue) { | ||
| return opt; | ||
| } | ||
| if (opt[optionsPropsName] || opt.options) { | ||
| const found = findDataItem( | ||
| opt[optionsPropsName] || opt.options || [], | ||
| ); | ||
| if (found) return found; | ||
| } | ||
| } | ||
| return null; | ||
| }; | ||
| foundDataItem = findDataItem(options); | ||
| } | ||
|
|
||
| // 如果value值为空则是清空时产生的回调,直接传值就可以了 | ||
| if (!value || !foundDataItem) { | ||
| const originalLabel = getOriginalLabel(foundDataItem, value); | ||
| const changedValue = value | ||
| ? { | ||
| ...value, | ||
| label: originalLabel, | ||
| } | ||
| : value; | ||
| onChange?.(changedValue, optionList, ...rest); | ||
| } else { | ||
| // 确保使用 dataItem.label(原始字符串),避免使用 value.label(可能是 optionItemRender 渲染的组件) | ||
| const originalLabel = getOriginalLabel(foundDataItem, value); | ||
| onChange?.( | ||
| { | ||
| ...value, | ||
| ...foundDataItem, | ||
| label: originalLabel, | ||
| }, | ||
| optionList, | ||
| ...rest, | ||
| ); | ||
| } | ||
| return; | ||
| showSearch.onSearch?.(''); | ||
| } | ||
| // 合并值 | ||
| const mergeValue = getMergeValue(value, optionList) as any; | ||
| onChange?.(mergeValue, optionList, ...rest); | ||
|
|
||
| // 将搜索结果置空,重新搜索 | ||
| onChange?.(value, optionList, ...rest); |
| /** 防抖动时间 默认10 单位ms */ | ||
| debounceTime?: number; | ||
| /** 自定义搜索方法, 返回搜索结果的 Promise */ | ||
| request?: (params: { query: string }) => Promise<DataValueType<T>[]>; | ||
| /** 指定组件中的值 */ | ||
| value?: KeyLabel | KeyLabel[]; |
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Added a mechanism to ensure that only the latest data request result is used, preventing outdated responses from overwriting new data. This enhancement improves the reliability of data fetching in the Select component.
… fetching" This reverts commit 3a41bea.
Updated the ProSchemaValueEnumMap type definition to only accept string and number as keys, removing boolean for improved type safety and clarity.
Streamlined the search handling logic in the SearchSelect component by removing unnecessary fetchData calls and consolidating the onSearch invocation. This change enhances clarity and maintains consistent behavior with the search functionality.
Summary by CodeRabbit
发布说明
Refactor
SearchSelect现在接收必填的options,移除defaultSearchValue;优化在请求/showSearch场景下的搜索、清空、聚焦与重置联动,并支持将request透传到搜索逻辑。Bug Fixes
value类型,仅支持字符串或数字。Tests
showSearch、fetchDataOnSearch、分组过滤、清空等交互测试。