#javascript #reactjs #typescript #material-ui #react-hook-form
#javascript #reactjs #typescript #материал-пользовательский интерфейс #react-hook-form
Вопрос:
Я пытаюсь создать общий компонент автозаполнения с помощью компонента автозаполнения пользовательского интерфейса, react-hook-form и моих пользовательских хуков.
Что он должен делать: при вводе пользователем (после каждой буквы) должен быть вызов api, список параметров в автозаполнении должен быть соответствующим образом обновлен.
В чем моя проблема: многие повторные отправки дочерних и родительских компонентов (также при быстром вводе или удалении пользователем возникает некоторое отставание, скорее всего, связанное с повторными отправками). Я думаю, что должен быть способ избежать такого поведения с помощью react-hook-form, который я пытаюсь использовать, поскольку автозаполнения являются полями формы.
Может кто-нибудь сказать мне, что мой подход неправильный? Я не могу сильно изменить хук, содержащий вызов api. Может быть, у кого-то уже была подобная проблема? Я попытался обернуть автозаполнение mui с помощью контроллера из react-hook-form, но это не очень помогло. Компонент Location повторно отображается примерно 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 amp;amp; onChange(value) }
options={options}
renderInput={(parameters) => (
<TextField
{...parameters}
error={Boolean(errors amp;amp; errors[name])}
helperText={errors amp;amp; errors[name]?.message}
id={name}
inputRef={registerInput}
name={name}
placeholder={placeholder}
rowsMax="1"
/>
)}
/>
</div>
);
}
Используйте хук автозаполнения:
Содержит вызов api, который возвращает объект типа:
{
//array of resuls
data: [],
isLoading: boolean
}