Правильный способ использования контроллера формы реакции с автозаполнением Material-UI - PullRequest
1 голос
/ 07 мая 2020

Я пытаюсь использовать пользовательский компонент Material-UI Autocomplete и подключить его к react-hook-form.

TL; DR: необходимо использовать автозаполнение MUI с контроллером формы реакции без defaultValue

Мой настраиваемый компонент Autocomplete принимает объект со структурой {_id:'', name: ''}, он отображает имя и возвращает _id при выборе опции. Autocomplete работает нормально.

<Autocomplete
  options={options}
  getOptionLabel={option => option.name}
  getOptionSelected={(option, value) => option._id === value._id}
  onChange={(event, newValue, reason) => {
    handler(name, reason === 'clear' ? null : newValue._id);
  }}
  renderInput={params => <TextField {...params} {...inputProps} />}
/>

Чтобы заставить его работать с react-hook-form, я установил setValues как обработчик для onChange в Autocomplete и вручную зарегистрировал компонент в useEffect следующим образом:

useEffect(() => {
  register({ name: "country1" });
},[]);

Это работает нормально, но я бы не хотел иметь ловушку useEffect и просто как-то напрямую использовать регистр.

Затем я попытался использовать компонент Controller из react-hook-form, чтобы правильно зарегистрировать поле в форме, а не использовать useEffect hook

<Controller
  name="country2"
  as={
    <Autocomplete
      options={options}
      getOptionLabel={option => option.name}
      getOptionSelected={(option, value) => option._id === value._id}
      onChange={(event, newValue, reason) =>
        reason === "clear" ? null : newValue._id
      }
      renderInput={params => (
        <TextField {...params} label="Country" />
      )}
    />
  }
  control={control}
/>

Я изменил onChange в компоненте Autocomplete, чтобы вернуть значение напрямую, но, похоже, это не работает.

Использование inputRef={register} на <TextField/> не поможет мне, потому что я хочу сохранить _id, а не name

ЗДЕСЬ рабочая песочница с двумя корпусами. Первый с useEffect и setValue в Autocomplete, который работает. Вторая моя попытка использовать Controller компонент

Любая помощь приветствуется.

LE

После комментария Билла с рабочей песочницей MUI Autocomplete, мне удалось получить функциональный результат

<Controller
  name="country"
  as={
    <Autocomplete
      options={options}
      getOptionLabel={option => option.name}
      getOptionSelected={(option, value) => option._id === value._id}
      renderInput={params => <TextField {...params} label="Country" />}
    />
  }
  onChange={([, { _id }]) => _id}
  control={control}
/>

Единственная проблема в том, что я получаю MUI Error в консоли

Material-UI: компонент меняется состояние неконтролируемого значения Autocomplete, которое необходимо контролировать.

Я пытался установить для него defaultValue, но он все равно ведет себя так. Также я бы не хотел устанавливать значение по умолчанию из массива параметров из-за того, что эти поля в форме не требуются.

Обновленная песочница ЗДЕСЬ

Любая помощь по-прежнему очень ценится

1 Ответ

4 голосов
/ 11 мая 2020

Итак, я исправил это. Но он выявил то, что я считаю ошибкой в ​​автозаполнении.

Сначала ... специально для вашей проблемы, вы можете устранить MUI Error, добавив defaultValue к <Controller> . Но это было только начало другого раунда или проблем.

Проблема в том, что функциям для getOptionLabel, getOptionSelected и onChange иногда передается значение (т.е. _id в данном случае ) и иногда передавал структуру опций - как и следовало ожидать.

Вот код, который я наконец придумал:

import React from "react";
import { useForm, Controller } from "react-hook-form";
import { TextField } from "@material-ui/core";
import { Autocomplete } from "@material-ui/lab";
import { Button } from "@material-ui/core";
export default function FormTwo({ options }) {
  const { register, handleSubmit, control } = useForm();

  const getOpObj = option => {
    if (!option._id) option = options.find(op => op._id === option);
    return option;
  };

  return (
    <form onSubmit={handleSubmit(data => console.log(data))}>
      <Controller
        name="country"
        as={
          <Autocomplete
            options={options}
            getOptionLabel={option => getOpObj(option).name}
            getOptionSelected={(option, value) => {
              return option._id === getOpObj(value)._id;
            }}
            renderInput={params => <TextField {...params} label="Country" />}
          />
        }
        onChange={([, obj]) => getOpObj(obj)._id}
        control={control}
        defaultValue={options[0]}
      />
      <Button type="submit">Submit</Button>
    </form>
  );
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...