news 2026/9/11 18:17:30

如何用 useAutoComplete 在 Refine Material UI 中实现远程搜索选择?

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
如何用 useAutoComplete 在 Refine Material UI 中实现远程搜索选择?

如何用 useAutoComplete 在 Refine Material UI 中实现远程搜索选择?

【免费下载链接】refineA React Framework for building internal tools, admin panels, dashboards & B2B apps with unmatched flexibility.项目地址: https://gitcode.com/GitHub_Trending/re/refine

在 Refine 的 Material UI 集成包(@refinedev/mui)中,当某个资源(例如categories)的记录需要作为下拉选项、且输入框内容要触发对后端的搜索请求时,可以用useAutocompletehook 管理 Material UI 的<Autocomplete>组件。它内部基于useListhook 取数,通过 dataProvider 的getList方法把filterspaginationsorters等参数发给 API,因此“输入即搜索”的远程过滤能力来自onSearch属性,而不是前端对已加载数据的本地过滤。本文以categories资源为例,给出从基础接入到远程搜索、再到与表单结合的完整路径。

准备条件

  • 一个已接入 Refine 的 React 应用,安装了@refinedev/mui,并在<Refine/>中配置了dataProvideruseAutocomplete依赖其中的getList方法取数);
  • 目标资源已在应用中可用,本文示例统一使用resource: "categories",其记录形如:
interface ICategory { id: number; title: string; }

第一步:接入 useAutocomplete 获取基础选项

最小用法是传入resource,然后把返回的autocompleteProps整体展开到<Autocomplete>上:

import { useAutocomplete } from "@refinedev/mui"; import { Autocomplete, TextField } from "@mui/material"; interface ICategory { id: number; title: string; } const PostCreate: React.FC = () => { const { autocompleteProps } = useAutocomplete<ICategory>({ resource: "categories", }); return ( <Autocomplete {...autocompleteProps} getOptionLabel={(item) => item.title} isOptionEqualToValue={(option, value) => value === undefined || option?.id?.toString() === (value?.id ?? value)?.toString() } placeholder="Select a category" renderInput={(params) => ( <TextField {...params} label="Category" margin="normal" variant="outlined" required /> )} /> ); };

autocompleteProps中包含optionsloadingonInputChangefilterOptions四个属性,直接展开即可。完整可运行项目可参考仓库中的 field-material-ui-use-autocomplete 示例,hook 的实现见 useAutocomplete 源码。

第二步:用 onSearch 实现远程搜索

这是标题任务的核心。给useAutocomplete传一个onSearch回调,它接收输入框的文本值,返回一组CrudFilters结构的过滤条件,条件会经useList传给dataProvidergetList,由后端执行过滤:

const { autocompleteProps } = useAutocomplete<ICategory>({ resource: "categories", onSearch: (value) => [ { field: "title", operator: "contains", value, }, ], });

两点需要注意:

  1. onSearch一旦被使用,会覆盖已有的filters属性,两者不要同时依赖;
  2. 输入过程会频繁触发请求,可配合debounce属性做防抖(单位毫秒):
useAutocomplete({ resource: "categories", onSearch: (value) => [ { field: "title", operator: "contains", value }, ], debounce: 500, });

从源码可以看到触发机制:autocompleteProps.onInputChange在输入事件类型为change时调用onSearch(value),类型为click(展开下拉)时调用onSearch("")。因此输入会带搜索词重新请求,点击展开则按空搜索词重新拉取。

可选分支:改为客户端过滤

如果数据量不大、不希望每次输入都请求后端,可以把onSearch显式传为undefined,禁用服务端过滤,改用 Material UI 的createFilterOptions在本地过滤:

import { createFilterOptions } from "@mui/material"; const { autocompleteProps } = useAutocomplete({ resource: "categories", }); const filterOptions = createFilterOptions({ matchFrom: "start", stringify: (option: any) => option.title, }); <Autocomplete {...autocompleteProps} getOptionLabel={(item) => item.title} onInputChange={(event, value) => {}} filterOptions={filterOptions} // 其余 props 同基础用法 />

这是文档明确给出的替代路径:远程搜索与客户端过滤二选一,不要混在同一条操作链里。

与 useForm / CRUD 组件结合

在编辑已有记录时,表单里保存的往往是{ id: ... }对象。useAutocomplete支持与useForm(react-hook-form)结合,通过<Controller>把选中值写回表单字段:

import { Create, useAutocomplete } from "@refinedev/mui"; import { Box, Autocomplete, TextField } from "@mui/material"; import { useForm } from "@refinedev/react-hook-form"; import { Controller } from "react-hook-form"; const PostCreate: React.FC = () => { const { saveButtonProps, refineCore: { formLoading, query }, register, control, formState: { errors }, } = useForm<IPost, HttpError, IPost & { category: ICategory }>(); const { autocompleteProps } = useAutocomplete<ICategory>({ resource: "categories", }); return ( <Create isLoading={formLoading} saveButtonProps={saveButtonProps}> <Box component="form"> <Controller control={control} name="category" rules={{ required: "This field is required" }} render={({ field }) => ( <Autocomplete {...autocompleteProps} {...field} onChange={(_, value) => { field.onChange(value); }} getOptionLabel={({ title }) => title} isOptionEqualToValue={(option, value) => value === undefined || option?.id?.toString() === (value?.id ?? value)?.toString() } placeholder="Select a category" renderInput={(params) => ( <TextField {...params} label="Category" margin="normal" variant="outlined" error={!!errors.category} helperText={errors.category?.message} required /> )} /> )} /> </Box> </Create> ); };

useAutocomplete也可以完全独立于useForm使用,上例只是文档给出的组合方式。

defaultValue:保证只有 id 时也能显示选中项

编辑页面经常只拿到id,而该记录可能不在当前分页拉到的选项里,<Autocomplete>会因此显示异常。传defaultValue后,hook 会额外发起一次useMany查询把该记录取回来并并入options

useAutocomplete({ resource: "categories", defaultValue: 1, // 或 [1, 2] });

注意:defaultValue不会设置默认选中,它只保证该值存在于选项列表中。要设置默认选中,应通过useFormdefaultValues<Autocomplete>value传入:

const form = useForm({ defaultValues: { category: { id: 1 }, // 默认选中值 }, }); const { autocompleteProps } = useAutocomplete({ resource: "categories", defaultValue: [1], // 确保默认值出现在选项中 });

若希望已选记录显示在选项列表顶部而非底部,可用selectedOptionsOrder: "selected-first"(默认"in-place"排在底部)。

验证是否生效

  • 选项是否来自后端autocompleteProps.loadingquery.isFetching || defaultValueQuery.query.isFetching,请求发出到返回期间为true,说明数据确实经由getList拉取;
  • 搜索是否走远程:输入文本时观察网络请求,getList请求应携带onSearch返回的过滤条件(如title contains ...);点击展开下拉时请求以空搜索词发起;
  • 搜索不生效时的排查入口:文档明确指出,默认行为是用useList取数并把搜索条件作为参数发出,若结果不对,应检查自己 dataProvider 中getList函数如何处理filters参数——filterssorterspagination都只是被透传给getList,后端不识别这些参数时过滤不会生效。

其他常用参数(均直接透传给getList或作为查询选项):sorters控制选项排序(如{ field: "title", order: "asc" });pagination支持currentPagepageSizemode"off"/"client"/"server");queryOptions透传给底层useQuery(如{ retry: 3 });meta可向 dataProvider 方法传额外信息(如自定义请求头);多 dataProvider 场景用dataProviderName指定。

更多细节见文档 useAutocomplete,其中还包含实时更新(liveModeonLiveEvent,需要配置LiveProvider)与successNotification/errorNotification(需要NotificationProvider)等可选能力。

【免费下载链接】refineA React Framework for building internal tools, admin panels, dashboards & B2B apps with unmatched flexibility.项目地址: https://gitcode.com/GitHub_Trending/re/refine

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/11 18:16:50

倒立红桃:符号倒置视觉实验的拍摄全解析

拿到“A16&#xff1a;倒立的红桃”这个项目编号时&#xff0c;我正坐在工作台前整理素材&#xff0c;桌上扔着一副旧扑克牌&#xff0c;红桃A的图案因为反复摩挲&#xff0c;边缘已经微微起毛。这个编号不是我随手乱写的&#xff0c;A16是我“符号倒置实验”系列的第十六张档案…

作者头像 李华
网站建设 2026/9/11 18:16:40

如何为 Flutter devicelab 编写新的内存测试用例并接入 CI

如何为 Flutter devicelab 编写新的内存测试用例并接入 CI 【免费下载链接】flutter Flutter makes it easy and fast to build beautiful apps for mobile and beyond 项目地址: https://gitcode.com/GitHub_Trending/flutter41/flutter Flutter 的 CI 系统会对每个 co…

作者头像 李华
网站建设 2026/9/11 18:13:07

深度迁移学习水质预测算法源码解析与实战指南

简介&#xff1a;基于深度迁移学习的水质预测研究算法源码&#xff0c;是一份面向计算机、数学、电子信息等专业课程设计、期末大作业及毕设项目的完整工程代码。项目以水质预测为应用场景&#xff0c;覆盖数据加载、时间特征生成、模型构建、迁移学习训练和结果评估等环节&…

作者头像 李华
网站建设 2026/9/11 18:07:43

2026年IT从业者必备的5大黄金认证与备考策略

1. 为什么2026年IT从业者需要职业护身符&#xff1f;过去三年里&#xff0c;我面试过上百位技术候选人&#xff0c;发现一个明显趋势&#xff1a;2023年头部企业的技术岗位JD中&#xff0c;83%明确要求特定技术认证。这不是偶然——当ChatGPT能写基础代码、低代码平台吞噬初级岗…

作者头像 李华
网站建设 2026/9/11 18:07:21

G-Helper:单文件替代奥创的笔记本控制工具

G-Helper&#xff1a;单文件替代奥创的笔记本控制工具 【免费下载链接】g-helper Lightweight Armoury Crate alternative for Asus laptops with nearly the same functionality. Works with ROG Zephyrus, Flow, TUF, Strix, Scar, ProArt, Vivobook, Zenbook, Expertbook, R…

作者头像 李华