如何解决Material UI - 使用 React Hook 表单自动完成
我正在使用 Material UI 的自动完成功能构建一个表单,并使用反冲进行状态管理。我也在使用 react-hook-form。我需要满足以下条件:
- 需要预先输入,允许输入的第一个字母从 API 返回选项列表以显示在自动完成中。每个字母都会返回不同的选项列表以供选择。
- 还需要允许 freeSolo,以便用户可以手动输入值
- 需要被要求并遵循某种模式来验证表单。
我使用 react-hook-form 的 <Controller>
来控制输入并允许验证、在帮助文本中显示错误消息等功能。
问题:我在根据我输入的内容过滤选项以及允许 freeSolo 时遇到了问题。当我输入一个新值时,选项列表不会过滤。弹出窗口只是保持打开状态。我还需要验证模式验证的输入更改。我尝试使用以下带有 onInputChange
的示例来利用 react-hook-form 的 useForm
和 setValue
手动设置字段的值并验证表单。 ({shouldValidate: true}
)。下面的示例是我为 Autocomplete 创建的自定义、可重用组件,以及在其他父组件中使用该自定义组件。我希望我提供了尽可能多的细节,但如果没有,请让我知道您是否需要更多信息。任何帮助将不胜感激!
父组件:
const setTrainType = useSetRecoilState(TrainType)
// Trains would return a list of trains based on letter of train type that was passed from input
const trainsList = useRecoilValue(Trains)
const trainoptions = useMemo(() => trainsList.map(trainIDFormatted),[
trainsList,])
const handleInputChange = useCallback(
(_e: unkNown,option: string,reason: string) => {
const capitalized =
option === capitalize(option) ? option : capitalize(option)
setValue('trainID',capitalized,{shouldValidate: true})
if (['input','reset'].includes(reason) && capitalized !== '') {
setTrainType(capitalized.charat(0))
} else {
setTrainType(undefined)
}
},[setTrainType,setValue],)
<Autocomplete
autoSelect
freeSolo
disabled={disabled}
helperText=" "
label="Select a train"
name="trainID"
options={trainoptions}
rules={{
pattern: {
message: 'Must match train ID pattern',value: /^(?:[A-Z]-?[A-Z ]{6}-?[0-9 ]-?[0-9 ]{2}[A-Z ])?$/,},required: 'Train is required',}}
onInputChange={handleInputChange}
/>
import {
AutocompleteProps,Autocomplete as MuiAutocomplete,} from '@material-ui/lab'
import {get} from 'lodash'
import React,{ReactNode,useCallback} from 'react'
import {
Controller,ControllerProps,FieldError,useFormContext,} from 'react-hook-form'
import {useRenderInput} from './hooks'
interface Props
extends Pick<ControllerProps<'select'>,'rules'>,Omit<
AutocompleteProps<string,false,true>,'error' | 'onChange' | 'required' | 'renderInput'
> {
helperText?: ReactNode
label?: string
name: string
}
/**
* Render controlled autocomplete. Use react-form-hook's FormProvider.
* @param props Component properties
* @param props.helperText Default helper text for error
* @param props.label Input label
* @param props.name Name identifier for react-hook-form
* @param props.required If true then item is required
* @param props.rules Select rules
* @return React component
*/
export const Autocomplete = ({
helperText,label,name,rules,...props
}: Props) => {
// eslint-disable-next-line @typescript-eslint/unbound-method
const {control,errors,watch} = useFormContext()
const error: FieldError | undefined = get(errors,name)
const required = get(rules,'required') !== undefined
const value = watch(name)
const renderAutocompleteInput = useRenderInput({
error: error !== undefined,helperText: get(error,'message',helperText),required,})
const handleOnChange = useCallback(
(_e: unkNown,option: string | null) => option,[],)
const renderAutocomplete = useCallback(
params => (
<MuiAutocomplete
{...props}
{...params}
renderInput={renderAutocompleteInput}
onChange={handleOnChange}
/>
),[handleOnChange,props,renderAutocompleteInput],)
return (
<Controller
control={control}
defaultValue={value ?? ''}
name={name}
render={renderAutocomplete}
rules={rules}
/>
)
}
它的样子:
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。