javascript - 如何使用 MUI 自动完成、react-hook-form 和自定义钩子构建异步自动完成组件(React 和 TS)
问题描述
我正在尝试使用 Material UI 自动完成组件、react-hook-form 和我的自定义挂钩构建一个通用的自动完成组件。
它应该做什么:在用户输入(每个字母之后)应该调用 api,自动完成中的选项列表应该相应更新。
我的问题是什么:子组件和父组件的许多重新渲染(当用户快速键入或删除时,很可能与重新渲染有关)。我认为应该有一种方法可以使用 react-hook-form 来避免这种行为,我正在尝试使用它,因为自动完成是表单字段。
有人能告诉我我的方法错了吗?我无法真正改变包含调用 api 的钩子。也许有人已经有类似的问题了?我尝试使用 react-hook-form 中的控制器包装 mui 自动完成功能,但并没有太大帮助。当用户输入他想要的内容并将其删除时,位置组件被重新渲染了 130 次。任何想法如何使这项工作?
它目前的样子:
表单组件(带有 RHF 提供程序的上下文)
import React from 'react';
import { useForm, FormProvider } from 'react-hook-form';
export default function UserForm(): JSX.Element {
const methods = useForm();
const handleSkip = (): void => {
console.log('skipped');
};
const onSubmit = useCallback((rawFormData) => {
console.log(rawFormData);
}, []);
return (
<FormProvider {...methods}>
<form onSubmit={methods.handleSubmit(onSubmit)}>
<Location />
<Actions>
<SubmitButton isPending={false}>Submit</SubmitButton>
</Actions>
</Form>
</FormProvider>
);
}
地点:
import React, { useState } from 'react';
import { useFormContext } from 'react-hook-form';
export default function Location(): JSX.Element {
const { register } = useFormContext();
const [selectedCountry, setSelectedCountry] = useState(null);
const [nameOfCountry, setNameOfCountry] = useState('');
const { data: countries} = useAutocomplete(nameOfCountry);
return (
<div>
<CustomAutocomplete
autocompleteOptions={countries}
name='country'
onInputChange={setSelectedCountry}
placeholder='country'
registerInput={register()}
/>
</div>
);
}
自定义自动完成:
import React, { SetStateAction, Dispatch, Ref, useState, useEffect } from 'react';
import { TextField } from '@material-ui/core';
import Autocomplete from '@material-ui/lab/Autocomplete';
import { useFormContext, Controller } from 'react-hook-form';
interface Properties {
name: string;
placeholder: string;
autocompleteOptions: string[];
onInputChange?: Dispatch<SetStateAction<string>>;
onChange?: Dispatch<SetStateAction<string>>;
isLoading?: boolean;
registerInput: Ref<any>;
}
CustomAutocomplete.defaultProps = {
isLoading: false,
onChange: (value: Record<string, never>) => value,
onInputChange: (value: string) => value,
};
export default function CustomAutocomplete({
name,
placeholder,
autocompleteOptions,
onInputChange,
isLoading,
onChange,
registerInput,
}: Properties): JSX.Element {
const { errors } = useFormContext();
const options = autocompleteOptions || [];
return (
<div>
<Autocomplete
freeSolo
getOptionLabel={(option: Country | string) => option.name || option}
id="input-autocomplete"
onInputChange={(event, value) => {
onInputChange(value);
}}
openOnFocus={false}
// onChange={(event, value) => onChange && onChange(value) }
options={options}
renderInput={(parameters) => (
<TextField
{...parameters}
error={Boolean(errors && errors[name])}
helperText={errors && errors[name]?.message}
id={name}
inputRef={registerInput}
name={name}
placeholder={placeholder}
rowsMax="1"
/>
)}
/>
</div>
);
}
使用自动完成钩子:
包含对 api 的调用返回对象,例如:
{
//array of resuls
data: [],
isLoading: boolean
}
解决方案
推荐阅读
- python - 如何使用 numpy 随机选择来获得具有相同数字的逐渐更长的序列?
- sql - 如何根据不同的行值在变量中创建新级别?
- arcgis - 当我使用 CDO 和 ArcGIS 从 netCDF 文件中提取同一网格点的数据时,为什么会得到不同的值?
- docker - 在 Windows 服务器上拉取 docker 映像时连接被拒绝
- c# - 当表单在 Blazor 服务器应用程序中具有有效状态时启用按钮
- weblogic12c - Oracle Service Bus 错误:ClassCastException:无法将 CountingRequestWrapper 强制转换为 ServletRequestImpl
- sql - 将连接查询中的重复值限制为仅显示第一个实例
- windows - 如何在 macOS 和 Windows 之间管理 docker-compose.override.yml 文件?
- nginx-reverse-proxy - 使用 nginx proxy_pass 在浏览器中保留 url 不起作用
- python - Tensorflow:使用 Tensorflow 2.5.0 将 Save_mode.pb 转换为 freeze_graph.pb