ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Refine v5 useAutocomplete 钩子完全指南:为 Material UI Autocomplete 构建数据驱动的选项列表

Refine v5 useAutocomplete 钩子完全指南:为 Material UI Autocomplete 构建数据驱动的选项列表 Refine v5 useAutocomplete 钩子完全指南为 Material UI Autocomplete 构建数据驱动的选项列表【免费下载链接】refineA React Framework for building internal tools, admin panels, dashboards B2B apps with unmatched flexibility.项目地址: https://gitcode.com/GitHub_Trending/re/refine导读useAutocomplete是 Refine v5 中面向 Material UIMUIAutocomplete组件提供的专用数据钩子它让开发者能够以极少的样板代码把后端资源如categories、tags的列表记录直接映射为下拉选择框的选项。本文以 文档原文 为核心骨架结合仓库中 useAutocomplete 源码、其底层 useSelect 实现 以及完整可运行的 示例项目 进行深度扩充。读完本文你将掌握useAutocomplete的全部属性resource、sorters、filters、defaultValue、onSearch、meta、liveMode 等、返回值结构、与useForm的集成方式以及客户端/服务端过滤等边界场景的实战方案。认识 useAutocomplete作用与数据链路useAutocomplete用于管理 Material UI 的Autocomplete组件——当资源中的记录需要作为下拉选项时它就是首选钩子。从源码看useAutocomplete 的实现 本质上是 Refine 核心钩子useSelect的薄封装它调用useSelectCore(props)获取query、defaultValueQuery、onSearch、overtime再将这些数据组装成 MUI Autocomplete 可以直接消费的autocompleteProps对象。因此useAutocomplete的属性签名UseAutocompleteProps是通过PickUseSelectProps, resource OmitUseSelectProps, optionLabel | optionValue从useSelect的属性类型派生的——这意味着它继承了useSelect几乎全部能力只是移除了与 MUI Autocomplete 语义重复的optionLabel/optionValue选项的展示与取值逻辑交给 MUI 的getOptionLabel/isOptionEqualToValue处理。在数据获取层面useAutocomplete通过核心的useList钩子完成列表数据拉取底层调用dataProvider的getList方法详见 useList 文档。在 useSelect 源码 中可以确认这条链路const queryResult useListTQueryFnData, TError, TData({ resource: identifier, sorters, filters: filters.concat(search), pagination: { currentPage: pagination?.currentPage, pageSize: pagination?.pageSize ?? 10, mode: pagination?.mode, }, queryOptions, ... });也就是说resource、sorters、filters、pagination等属性都会被透传给getList作为查询参数发送给 API。基本用法一个最基础的调用只需指定resourceimport { useAutocomplete } from refinedev/mui; import { Autocomplete, TextField } from mui/material; const { autocompleteProps } useAutocomplete({ resource: categories, }); return ( Autocomplete {...autocompleteProps} getOptionLabel{(item) item.title} isOptionEqualToValue{(option, value) value undefined || option?.id?.toString() (value?.id ?? value)?.toString() } renderInput{(params) ( TextField {...params} labelCategory marginnormal variantoutlined required / )} / );useAutocomplete会通过useList拉取categories资源的列表数据并把autocompleteProps展开到Autocomplete上。autocompleteProps中已经内置了options、loading、onInputChange、filterOptions四个 MUI 必需属性见 源码中的组装逻辑其中filterOptions: (x) x意味着默认不做客户端过滤交由服务端过滤详见下文 onSearch 一节。实时更新Realtime此功能需要配置LiveProvider。当useAutocomplete挂载后它会向liveProvider的subscribe方法传递一些参数如channel、resource等从而订阅实时事件。当相关资源发生创建、更新、删除时选项列表可以随之自动刷新。如果你只需要按需更新可以配合liveMode与onLiveEvent精细控制见下文属性详解。属性详解resource必填resource会通过useList作为参数传给dataProvider的getList方法。它通常用作 API 端点路径具体如何处理取决于getList中的实现可参考 创建 data provider 一节useAutocomplete({ resource: categories, });如果存在同名资源你可以传入identifier来代替nameidentifier只作为资源的主匹配键data provider 的方法仍会使用Refine/组件中定义的资源name。更多信息见Refine/组件的 identifier 章节。sorterssorters用于控制选项的展示顺序它会通过useList透传给getList以排序查询参数的形式发给 APIuseAutocomplete({ sorters: [ { field: title, order: asc, }, ], });其类型为CrudSort[]字段field指定排序字段order为asc或desc。更多信息见 CrudSorting 接口文档。filtersfilters用于对选项进行过滤同样通过useList透传给getList以过滤查询参数发送给 APIuseAutocomplete({ filters: [ { field: isActive, operator: eq, value: true, }, ], });其类型为CrudFilter[]operator支持eq、ne、contains、gte、lte等取决于 data provider 的实现。更多信息见 CrudFilters 接口文档。defaultValuedefaultValue用于从 API 额外获取选项。当选项很多、需要分页时默认值可能不在当前可见列表中从而导致下拉框显示异常。为避免这个问题钩子会通过useMany查询单独拉取defaultValue对应的记录并合并进选项确保它一定存在于列表中。因为底层使用useManydefaultValue可以是单个值也可以是数组useAutocomplete({ defaultValue: 1, // 或 [1, 2] });注意defaultValue不会设置默认选中项它只保证默认值存在于选项列表中。要设置默认选中请把defaultValue传给Autocomplete的value属性或useFormconst form useForm({ defaultValues: { category: { id: 1 }, // 默认选中的值 }, }); const { autocompleteProps } useAutocomplete({ resource: categories, defaultValue: [1], // 确保默认值包含在选项中 });从 useSelect 源码 可以看到defaultValue查询的实现只有当defaultValues.length 0时useMany查询才会被启用enabled避免空值产生多余请求。selectedOptionsOrderselectedOptionsOrder用于控制defaultValue对应的选中项在选项列表中的排序方式可选值in-place把selectedOptions排在末尾默认值。selected-first把selectedOptions排在最前面。useAutocomplete({ defaultValue: 1, // 或 [1, 2] selectedOptionsOrder: selected-first, // in-place | selected-first });在 useAutocomplete 源码 中两种模式分别通过unionWith以不同顺序合并主查询结果与默认值查询结果并用isEqual去重底层 useSelect 则使用uniqBy(..., value)按选项值去重。更多细节见 useMany 文档。debouncedebounce用于对onSearch函数做防抖单位是毫秒。底层 useSelect 源码 使用lodash/debounce包装搜索回调默认防抖值为300msuseAutocomplete({ debounce: 500, });queryOptionsqueryOptions用于向内部的useQuery钩子传递额外的选项例如自定义重试次数useAutocomplete({ queryOptions: { retry: 3, }, });它在 useSelect 中 被定义为UseQueryOptionsGetListResponseTQueryFnData, TError, GetListResponseTData省略queryKey与queryFn。更多信息见 TanStack Query 的 useQuery 文档。paginationpagination会通过getList透传给 data provider用于发送分页查询参数。注意 useSelect 源码 中pageSize的默认值为10。currentPage指定当前页码useAutocomplete({ pagination: { currentPage: 2, }, });pageSize指定每页数量useAutocomplete({ pagination: { pageSize: 20, }, });mode指定分页模式可选off、client或server用于决定是否使用服务端分页useAutocomplete({ pagination: { mode: off, }, });defaultValueQueryOptions当传入defaultValue时钩子会调用useMany数据钩子获取选中记录。通过defaultValueQueryOptions可以修改这次查询的选项如果不传则复用queryOptions中给定的值见 useSelect 源码useAutocomplete({ resource: categories, defaultValueQueryOptions: { onSuccess: (data) { console.log(triggers when on query return on success); }, }, });onSearchonSearch允许你对选项进行“自动补全式”搜索。它在每次输入变化时把CrudFilter[]返回给列表查询useAutocomplete({ onSearch: (value) [ { field: title, operator: contains, value, }, ], });注意一旦使用onSearch它会覆盖已有的filters。在 useSelect 源码 中若提供了onSearchFromProp搜索状态会被设置为该函数的返回值否则使用默认的searchField默认取optionLabel对应的字段缺省为title配合contains运算符构造过滤条件。此外源码用useRef保存最新的onSearch回调避免闭包过期导致搜索失效index.ts。更多信息见 CrudFilters 接口文档。客户端过滤有时你希望在客户端过滤选项。此时可以把onSearch传为undefined来禁用服务端过滤然后使用 MUI 提供的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} isOptionEqualToValue{(option, value) value undefined || option?.id?.toString() (value?.id ?? value)?.toString() } placeholderSelect a category renderInput{(params) ( TextField {...params} labelCategory marginnormal variantoutlined required / )} /;另外在 useAutocomplete 源码 中可以确认autocompleteProps.onInputChange只在event.type change时触发onSearch(value)而在event.type click点击输入框时调用onSearch()以恢复完整选项列表。metameta是一个特殊属性用于向 data provider 方法传递附加信息常见用途针对特定用例定制 data provider 方法。使用纯 JavaScript 对象JSON生成 GraphQL 查询。更多信息见 General Concepts 文档中的 meta 章节。下面示例把headers通过meta传给getList同理你可以按需传递任何属性useAutocomplete({ meta: { headers: { x-meta-data: true }, }, }); const myDataProvider { //... getList: async ({ resource, pagination, sorters, filters, meta, }) { const headers meta?.headers ?? {}; const url ${apiUrl}/${resource}; //... const { data, headers } await httpClient.get(${url}, { headers }); return { data, }; }, //... };在 useSelect 源码 中meta会通过useMeta()与资源级别的 meta 合并成combinedMeta再分别传给useMany与useList。dataProviderName如果配置了多个dataProvider可以通过dataProviderName指定使用哪一个。当不同资源对应不同数据提供方时非常有用useAutocomplete({ dataProviderName: second-data-provider, });successNotification此功能需要配置NotificationProvider。数据获取成功后useAutocomplete会调用NotificationProvider的open函数展示成功通知。通过该属性可自定义通知内容useAutocomplete({ successNotification: (data, values, resource) { return { message: ${data.title} Successfully fetched., description: Success with no errors, type: success, }; }, });errorNotification此功能需要配置NotificationProvider。数据获取失败时钩子会调用open展示错误通知可用该属性自定义useAutocomplete({ errorNotification: (data, values, resource) { return { message: Something went wrong when getting ${data.id}, description: Error, type: error, }; }, });liveMode此功能需要配置LiveProvider。决定收到相关实时事件后是否自动更新数据auto自动更新manual手动更新。可用于在应用中实时展示数据useAutocomplete({ liveMode: auto, });更多信息见 Live / Realtime 文档。onLiveEvent此功能需要配置LiveProvider。订阅新事件到达时执行的回调函数useAutocomplete({ onLiveEvent: (event) { console.log(event); }, });liveParams此功能需要配置LiveProvider。传递给liveProvider的 subscribe 方法的参数。overtimeOptions如果你希望为耗时过长的请求展示加载提示可以传入overtimeOptionsinterval是毫秒级的时间间隔onInterval是每个间隔触发的回调。钩子会返回overtime对象其中elapsedTime为已经过的毫秒数请求完成时变为undefinedconst { overtime } useAutocomplete({ //... overtimeOptions: { interval: 1000, onInterval(elapsedInterval) { console.log(elapsedInterval); }, }, }); console.log(overtime.elapsedTime); // undefined, 1000, 2000, 3000 4000, ...实战中可配合展示“加载超时”提示{ elapsedTime 4000 divthis takes a bit longer than expected/div; }从 useSelect 源码 可以看到overtime的计时基于主查询与默认值查询的isFetching状态。返回值useAutocomplete返回以下对象属性说明类型autocompletePropsMaterial UI Autocomplete 属性AutoCompleteReturnValuesquery列表记录查询结果QueryObserverResult{ data: TData }defaultValueQuerydefaultValue记录的查询结果QueryObserverResult{ data: TData }defaultValueQueryOnSuccess默认值查询成功的回调() voidovertime加载超时相关属性{ elapsedTime?: number }其中autocompleteProps即AutoCompleteReturnValues具体包含属性说明类型options选项数组TDataloading加载状态booleanonInputChange输入值变化时触发(event: React.SyntheticEvent, value: string, reason: string) voidfilterOptions决定搜索时渲染哪些选项(options: TData, state: object) TData在 useAutocomplete 源码 中loading由query.isFetching || defaultValueQuery.query.isFetching计算得出因此主列表与默认值任一请求进行中都会显示加载状态。类型参数useAutocomplete是泛型钩子可显式指定三个类型参数属性说明类型默认值TQueryFnData查询函数返回的结果数据类型需继承BaseRecordBaseRecordBaseRecordTError自定义错误对象需继承HttpErrorHttpErrorHttpErrorTDataselect函数返回的结果数据类型需继承BaseRecord未指定时使用TQueryFnDataBaseRecordTQueryFnData例如在示例项目中可以这样使用const { autocompleteProps } useAutocompleteICategory({ resource: categories, });FAQ典型场景与边界问题如何确保 defaultValue 一定出现在选项中某些场景下我们只有记录的id却希望它在下拉框中显示为已选中状态。钩子内部会通过useMany发送请求、拿到数据并标记为选中。在示例项目的编辑页edit.tsx中有典型用法const { autocompleteProps } useAutocompleteICategory({ resource: categories, defaultValue: queryResult?.data?.data.category.id, });能否手动构造 options可以。useAutocomplete返回的query对象中包含原始数据你可以自行映射成新的optionsconst { autocompleteProps, query } useAutocomplete(); const options query.data?.data.map((item) ({ title: item.title, value: item.id, })); return Autocomplete {...autocompleteProps} options{options || []} /;如何与 CRUD 组件及 useForm 集成useAutocomplete可以与useForm独立配合使用。在 create.tsx 中通过react-hook-form的Controller把autocompleteProps与表单字段绑定Controller control{control} namecategory rules{{ required: This field is required }} render{({ field }) ( Autocomplete {...autocompleteProps} {...field} onChange{(_, value) { field.onChange(value); }} getOptionLabel{(item) { return ( autocompleteProps?.options?.find( (p) p?.id?.toString() item?.id?.toString(), )?.title ?? ); }} isOptionEqualToValue{(option, value) value undefined || option?.id?.toString() (value?.id ?? value)?.toString() } renderInput{(params) ( TextField {...params} labelCategory marginnormal variantoutlined error{!!errors.category} helperText{errors.category?.message} required / )} / )} /多选场景如 tags则配合multiple属性使用示例项目中通过tagsAutocompleteProps.options.filter(...)把已选 id 映射回完整选项对象再作为value见 create.tsx 与 edit.tsx。默认情况下Refine 使用useList钩子做搜索并把结果传给搜索参数。如果遇到问题请检查 data provider 的getList函数。若想改为客户端过滤可以参考上文“客户端过滤”一节的方案。运行示例仓库中的 field-material-ui-use-autocomplete 示例 提供了上述全部能力的完整可运行代码它演示了在创建页create.tsx与编辑页edit.tsx中如何用useAutocomplete渲染分类单选下拉框与标签多选下拉框并与useForm、react-hook-form无缝集成。进入该示例目录后安装依赖并启动开发服务器即可看到实际效果。【免费下载链接】refineA React Framework for building internal tools, admin panels, dashboards B2B apps with unmatched flexibility.项目地址: https://gitcode.com/GitHub_Trending/re/refine创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表