Reactjs 物料界面-使用反应挂钩表单自动完成

Reactjs 物料界面-使用反应挂钩表单自动完成,reactjs,material-ui,react-hook-form,recoiljs,Reactjs,Material Ui,React Hook Form,Recoiljs,我正在使用MaterialUI的自动完成功能构建表单,并使用反冲进行状态管理。我还使用了react-hook形式。我需要满足以下标准: 需要typeahead,它允许键入的第一个字母返回API中显示在自动完成中的选项列表。每个字母将返回一个不同的选项列表以供选择 还需要允许freeSolo,以便用户可以手动输入值 需要是必需的,并遵循一种模式来验证表单 我使用react hook表单的来控制输入,并允许验证、在帮助器文本中显示错误消息等功能 问题:我对基于我键入的内容筛选出的typeahead选

我正在使用MaterialUI的自动完成功能构建表单,并使用反冲进行状态管理。我还使用了react-hook形式。我需要满足以下标准:

  • 需要typeahead,它允许键入的第一个字母返回API中显示在自动完成中的选项列表。每个字母将返回一个不同的选项列表以供选择
  • 还需要允许freeSolo,以便用户可以手动输入值
  • 需要是必需的,并遵循一种模式来验证表单
  • 我使用react hook表单的
    来控制输入,并允许验证、在帮助器文本中显示错误消息等功能

    问题:我对基于我键入的内容筛选出的typeahead选项以及允许freeSolo存在问题。键入新值时,选项列表不会过滤。弹出窗口保持打开状态。我还需要对模式验证输入的更改进行验证。我尝试了以下示例,使用
    onInputChange
    使用react钩子表单的
    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}
                  />
    
    const setTrainType=UseSetRecocilState(列车类型)
    //Trains将根据输入传递的列车类型字母返回列车列表
    const trainsList=useRecoilValue(列车)
    const trainOptions=useMoom(()=>trainsList.map(trainIDFormatted)[
    列车名单,
    ])
    const handleInputChange=useCallback(
    (_e:unknown,option:string,reason:string)=>{
    常数资本化=
    选项===资本化(选项)?选项:资本化(选项)
    setValue('trainID',大写,{shouldValidate:true})
    如果(['input','reset'])。包括(原因)&大写!=''){
    setTrainType(大写字符(0))
    }否则{
    setTrainType(未定义)
    }
    },
    [setTrainType,setValue],
    )
    

    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, 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),
        label,
        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}
        />
      )
    }