资讯详情

资讯详情

refine 中 Ant Design `useSelect` Hook 基础用法完全指南:让 `<Select>` 与数据资源无缝对接

refine 中 Ant DesignuseSelectHook 基础用法完全指南让Select与数据资源无缝对接【免费下载链接】refineA React Framework for building internal tools, admin panels, dashboards B2B apps with unmatched flexibility.项目地址: https://gitcode.com/GitHub_Trending/re/refine导读useSelect是 refineReact 框架用于快速构建内部工具、后台面板与 B2B 应用为 Ant Design 的Select展开完整讲解如何用最少的代码把某个资源resource的数据拉取为下拉选项并深度剖析其底层实现useList数据获取、useMany默认值补充、selectProps的组装逻辑让你既会写、也懂原理。读完本文你将掌握useSelect的全部核心属性、与useForm的集成方式以及搜索、排序、默认值等常见实战场景的写法。一、useSelect是什么根据 v3 文档对useSelect的定义见 index.mduseSelecthook allows you to manage Ant DesignSelectcomponent when records in a resource needs to be used as select options.即当某个资源resource中的记录需要作为下拉选项时useSelect负责替你管理 Ant Design 的Select组件。它解决的核心痛点是传统写法里你需要自己调用数据获取 Hook、把记录映射成{ label, value }、处理加载态、处理搜索与分页——而useSelect把这些流程全部封装最终只暴露一个开箱即用的selectProps。它的数据来源是dataProvider的getList方法经由核心包的useListHook 触发因此它适用于任何实现了 refinedataProvider约定的后端REST、GraphQL、Supabase、Strapi 等。文档中明确指出本 Hook 使用useList获取数据参考 useList 文档。提示如果你在使用 Headless、MUI 或 Mantine 等不同 UI 体系refine 也提供了对等的选择器 Hook核心包useSelect、Material UI 的useAutocomplete、Mantine 的useSelect本文聚焦于 Ant Design 集成。二、基础用法一段代码完成资源 → 下拉选项文档中basic-usage-live-preview.md给出了最小可用示例在一个创建文章页面/posts/create中把categories分类资源渲染成下拉框。完整代码如下v3 文档中的包名为pankod/refine-antdimport { useSelect, Select } from pankod/refine-antd; interface ICategory { id: number; title: string; } const PostCreate: React.FC () { const { selectProps } useSelectICategory({ resource: categories, }); return ( Select placeholderSelect a category style{{ width: 300 }} {...selectProps} / ); };在示例环境中该组件被注册为posts资源的创建页setRefineProps({ resources: [ { name: posts, create: PostCreate, }, ], });这段代码的要点可拆解为三步声明资源useSelectICategory({ resource: categories })告诉 refine 要从categories这个资源拉取数据。泛型ICategory用于类型提示。解构selectPropsHook 返回的selectProps已包含options选项数组、onSearch搜索回调、loading加载态、showSearch等 Ant DesignSelect所需的一切 props。展开绑定Select {...selectProps} /一行展开即可获得一个会从 API 自动加载分类数据、支持搜索的下拉框。2.1selectProps到底装了什么打开 antd 包的 useSelect 实现 可以看到这个魔法其实非常直白antd 层的useSelect只是对核心包useSelect的一次适配封装把核心 Hook 返回的数据组装成 Ant Design 的SelectPropsexport const useSelect TQueryFnData, TError, TData, TOption(props) { const { query, defaultValueQuery, onSearch, options } useSelectCore...(props); return { selectProps: { options, onSearch, loading: defaultValueQuery.query.isFetching, showSearch: true, filterOption: false, }, query, defaultValueQuery: defaultValueQuery.query, }; };从源码结构看selectProps内部固定做了四件事options由核心 Hook 根据optionLabel/optionValue把记录映射成的选项数组onSearch供 Select 输入时触发的搜索回调默认带 300ms 防抖见下文loading绑定到defaultValueQuery的isFetching状态当默认值数据还在请求时显示加载中showSearch: true与filterOption: false默认开启搜索输入框并关闭前端本地过滤把过滤交给后端onSearch处理。因此你完全不需要手动维护options和loading状态。三、底层原理核心包useSelect的数据流水线antd 层的封装很薄真正的数据逻辑在核心包 packages/core/src/hooks/useSelect/index.ts。从源码可以看到它依次做了这些事维护搜索与选项状态用useState分别保存search搜索产生的CrudFilter[]、options当前选项和selectedOptions选中的选项设置默认值optionLabel title、optionValue id、debounce 300、defaultValue []、selectedOptionsOrder in-place、searchField默认为optionLabel字符串时列表数据把resource、filters、sorters、pagination、meta等透传给useList内部调用dataProvider.getList默认值数据当传入defaultValue时调用useMany内部调用dataProvider.getMany拉取默认选中项并追加进options避免当前页看不到默认值导致的显示断裂去重合并使用lodash的uniqBy合并列表数据与默认值数据防止重复选项映射选项用lodash.get支持optionLabel/optionValue的嵌套路径取值最终产出{ label, value }数组。其中debounce用lodash/debounce实现。核心包测试 index.spec.ts 中有专门用例验证默认 300ms 防抖下连续输入1、12、123只触发一次请求而设置debounce: 0后每次输入都会触发onSearch disabled debounce。四、核心属性详解来自 v3 文档下面按 v3 文档 index.md 的顺序逐一说明useSelect支持的全部属性。所有属性均为可选只有resource是必填的。4.1resource必填指定要读取的资源名会作为参数传给dataProvider的getList方法经由useList。它通常被用作 API 端点路径具体如何解析取决于getList的实现可参考文档中creating a data provider一节了解resource的处理方式useSelect({ resource: categories, });4.2optionLabel与optionValue用于自定义选项的label显示文本与value选中值取自记录的哪个字段。默认值分别为optionLabel title、optionValue id。useSelectICategory({ resource: products, optionLabel: name, optionValue: productId, });支持嵌套属性使用 lodash 的 Object path 语法即lodash.get的路径写法可以取嵌套字段const { options } useSelect({ resource: categories, optionLabel: nested.title, optionValue: nested.id, });4.3sort控制选项的展示顺序会传给getList生成排序查询参数对应CrudSorting接口详见 interfaceReferences.md 中的CrudSortinguseSelect({ sort: [ { field: title, order: asc, }, ], });文档配套的sort-live-preview.md还演示了动态排序玩法把order存入 React state配合一个按钮在asc/desc之间切换下拉选项会随排序状态实时刷新const [order, setOrder] React.useStateasc | desc(asc); const { selectProps } useSelectICategory({ resource: categories, sort: [ { field: title, order, } ] }); return ( Select placeholder{Ordered Categories: ${order}} style{{ width: 300 }} {...selectProps} / Button onClick{() setOrder(order asc ? desc : asc)}Toggle Order/Button / );4.4filters按条件过滤选项同样透传给getList生成过滤查询参数对应CrudFilters接口useSelect({ filter: [ { field: isActive, operator: eq, value: true, }, ], });注意文档示例中属性名写作filter而源码类型定义中该属性名为filtersfilters?: CrudFilter[]。使用时请以项目实际版本的类型定义为准传入filters数组。4.5defaultValue让某些选项默认被选中。它会给Select额外追加选项——这正是关键设计当数据量很大需要分页时默认值可能不在当前可见选项里直接设置会导致 Select 显示异常。为此useSelect会单独发起一次useMany查询参考 useMany 文档用defaultValue去后端取回对应记录并追加到选项数组确保默认值始终存在于当前选项中。defaultValue可以是单个值或数组useSelect({ defaultValue: 1, // or [1, 2] });4.6debounce对onSearch函数做防抖单位毫秒。核心包源码中的默认值是300useSelect({ resource: categories, debounce: 500, });传0可以关闭防抖测试用例onSearch disabled debounce (0ms)验证了此行为。4.7queryOptions透传给内部useQuery的额外选项即 TanStack Query 的useQuery配置比如重试次数useSelect({ queryOptions: { retry: 3, }, });4.8paginationcurrent/pageSize分页参数会传给getList用于向 API 发送分页查询参数useSelect({ pagination: { current: 2, }, });useSelect({ pagination: { pageSize: 20, }, });4.9hasPagination是否使用服务端分页。设为false时一次性拉取全部数据适合选项数量有限的场景useSelect({ hasPagination: false, });4.10defaultValueQueryOptions当传入defaultValue时会额外调用useMany查询默认选中记录用此属性可定制该查询的选项。如果不传则复用queryOptions中的值const { options } useSelect({ resource: categories, defaultValueQueryOptions: { onSuccess: (data) { console.log(triggers when on query return on success); }, }, });4.11onSearch搜索 / 自动补全允许你在下拉框输入时自动过滤AutoComplete选项。onSearch接收输入值返回一组CrudFilter随后的请求会带上这些过滤条件const { selectProps } useSelectICategory({ resource: categories, onSearch: (value) [ { field: title, operator: contains, value, } ] });注意一旦使用了onSearch它会覆盖现有的filters。客户端过滤模式如果你希望在前端本地过滤选项可以传onSearch{undefined}并把filterOption设为true同时用optionFilterProp指定按label还是value过滤const { selectProps } useSelect({ resource: categories, }); Select {...selectProps} onSearch{undefined} filterOption{true} optionFilterProplabel // or value /;需要说明antd 封装层默认把filterOption固定为false因此做纯客户端过滤时需要在展开selectProps之后再显式覆盖该属性。4.12metaDatametaData有两个用途一是向dataProvider方法传递附加信息二是用于以普通 JS 对象生成 GraphQL 查询。下面的例子把headers通过metaData传给getList自定义的 data provider 从中读取useSelect({ metaData: { headers: { x-meta-data: true }, }, }); const myDataProvider { getList: async ({ resource, pagination, hasPagination, sort, filters, metaData, }) { const headers metaData?.headers ?? {}; const url ${apiUrl}/${resource}; const { data, headers } await httpClient.get(${url}, { headers }); return { data, }; }, };4.13dataProviderName当存在多个dataProvider时指定本次使用哪一个不同资源可以用不同数据源useSelect({ dataProviderName: second-data-provider, });4.14successNotification与errorNotification需要配合NotificationProvider才能生效。数据获取成功/失败后可用这两个属性自定义通知内容。它们都是返回通知配置的函数useSelect({ successNotification: (data, values, resource) { return { message: ${data.title} Successfully fetched., description: Success with no errors, type: success, }; }, });useSelect({ errorNotification: (data, values, resource) { return { message: Something went wrong when getting ${data.id}, description: Error, type: error, }; }, });4.15 实时相关liveMode、onLiveEvent、liveParams需要配合LiveProvider使用。liveMode收到相关实时事件后选择auto自动更新数据还是manual手动更新onLiveEvent订阅到新事件时的回调函数liveParams传给liveProvider的subscribe方法的参数。useSelect({ liveMode: auto, });useSelect({ onLiveEvent: (event) { console.log(event); }, });Hook 挂载时会自动把channel、resource等参数传给liveProvider的subscribe方法从而订阅实时更新详见 live-provider 文档。五、与useForm/ CRUD 组件集成表单场景useSelect最常见的落地场景是配合useForm和Create/Edit等 CRUD 组件。文档crud-live-preview.md给出了标准写法把Select {...selectProps} /放进Form.Item并通过name绑定到表单字段这里绑定到嵌套字段[category, id]正好对应optionValue输出的idimport { Create, Form, Select, useSelect, useForm } from pankod/refine-antd; interface ICategory { id: number; title: string; } const PostCreate: React.FC () { const { formProps, saveButtonProps } useFormICategory(); const { selectProps } useSelectICategory({ resource: categories, }); return ( Create saveButtonProps{saveButtonProps} Form {...formProps} layoutvertical Form.Item labelCategory placeholderSelect a category name{[category, id]} rules{[ { required: true, }, ]} Select {...selectProps} / /Form.Item /Form /Create ); };仓库中的真实示例 create.tsx 展示了更完整的生产级用法同时使用多个useSelect分类 标签标签用modemultiple实现多选并在失焦时清空搜索条件const { selectProps: categorySelectProps } useSelectICategory({ resource: categories, onSearch: (value) [ { field: title, operator: contains, value, }, ], sorters: [ { field: title, order: asc, }, ], pagination: { mode: server, }, }); const { selectProps: tagSelectProps } useSelectICategory({ resource: tags, pagination: { mode: server, }, }); // 在 JSX 中 Form.Item labelCategory name{[category, id]} rules{[{ required: true }]} Select {...categorySelectProps} / /Form.Item Form.Item labelTags name{[tags]} rules{[{ required: true }]} Select {...tagSelectProps} onBlur{() tagSelectProps?.onSearch?.()} modemultiple / /Form.Item六、FAQ四个高频问题速查6.1 如何给选项加搜索AutoComplete用onSearch它负责设置搜索值并返回过滤条件参考上文 4.11 节配合pankod/refine-antd导出的useSelect即可实现服务端搜索。6.2 如何确保defaultValue一定出现在选项中当只有id而选项尚未加载时Hook 会通过useMany发起请求取回对应记录并标记为已选中见 4.5 节示例见 default-value-live-preview.md。6.3 如何修改选项的label与value用optionLabel与optionValue默认title与id。例如改为name与categoryIduseSelect({ optionLabel: name, optionValue: categoryId, });6.4 能否完全手动构造选项可以。当optionLabel/optionValue不够用时直接使用queryResult自己映射const { queryResult } useSelect(); const options queryResult.data?.data.map((item) ({ label: item.title, value: item.id, })); return Select options{options} /;七、返回值一览v3 文档给出的返回值如下属性说明类型selectPropsAnt Design Select 的 props直接展开使用SelectPropsqueryResult列表查询的结果QueryObserverResult{ data: TData }defaultValueQueryResultdefaultValue记录的查询结果QueryObserverResult{ data: TData }defaultValueQueryOnSuccess默认值查询成功时的回调() void补充说明从当前仓库主干源码 index.ts 看antd 层返回的字段已演进为selectProps、query、defaultValueQuery核心包 packages/core/src/hooks/useSelect/index.ts 还额外返回onSearch、options以及useLoadingOvertime的超时相关能力。不同版本命名略有差异请以你所使用的 refine 版本的类型定义为准。八、测试与示例到哪里看完整可运行代码单元测试packages/antd/src/hooks/fields/useSelect/index.spec.ts 覆盖了选项生成options长度与内容、自定义optionLabel/optionValue函数、onSearch的默认 300ms 防抖与debounce: 0禁用等行为是理解实现语义的第一手资料。基础示例examples/field-antd-use-select-basic 对应文档末尾的field-antd-use-select-basic示例包含create、edit、list三页的完整useSelect集成代码。无限加载示例field-antd-use-select-infinite对应 examples/field-antd-use-select-infinite演示了配合useInfiniteList的无限滚动加载选项的用法适合选项量极大的场景。结语useSelect是 refine 中最能体现声明式数据绑定设计哲学的 Hook 之一你只需声明resource把selectProps展开到Select上剩下的数据获取、选项映射、加载态、搜索防抖与默认值补齐都由框架完成。理解它的封装层次antd 适配层 → 核心数据层useList/useMany之后你就能在真实业务中自如地组合filters、sorters、onSearch与pagination写出既简洁又高性能的后台表单。【免费下载链接】refineA React Framework for building internal tools, admin panels, dashboards B2B apps with unmatched flexibility.项目地址: https://gitcode.com/GitHub_Trending/re/refine创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
觉得有用,分享给同行:

为您的企业打造数字门面

稳重轻奢商务风格,端正雅致视觉,长效耐看不易过时。

立即咨询 →