繁体   English   中英

MUI 自动完成和 react-hook-form 不显示带有获取数据的选定选项

[英]MUI Autocomplete and react-hook-form not displaying selected option with fetched data

我在来自反应钩子表单的表单中有一个 MUI 自动完成功能,它在填写表单时工作正常,但是当我想显示填充了获取数据的表单时,MUI 自动完成功能仅在两次渲染后显示所选选项。

我认为这与 useEffect 和重置(来自反应挂钩形式)有关,因为选项为 static 的自动完成功能工作正常,但我还必须从我的 API 获取选项的自动完成功能仅在第二次运行 useEffect 后才能正常工作。

我无法重现 codesandbox,因为它是一个消耗真实 api 的大型项目,但如果需要,我可以提供更多信息。 如果有人可以帮助我,请提前致谢。

我选择要在表单内可视化的项目的页面:

const People: React.FC = () => {

  const [show, setShow] = useState(false);
  const [modalData, setModalData] = useState<PeopleProps>({} as PeopleProps);

  async function showCustomer(id: string) {
    await api
      .get(`people/${id}`)
      .then((response) => {
        setModalData(response.data);
        setShow(true);
      })
      .catch((error) => toast.error('Error')
      )
  }

  return (
    <>
      {...} // there's a table here with items that onClick will fire showCustomer() 

      <Modal
        data={modalData}
        visible={show}
      />
    </>
  );
};

我在模态中的形式:

const Modal: React.FC<ModalProps> = ({data, visible}) => {
  const [situations, setSituations] = useState<Options[]>([]);
  const methods = useForm<PeopleProps>({defaultValues: data});
  const {reset} = methods;

  /* FETCH POSSIBLE SITUATIONS FROM API*/
  useEffect(() => {
    api
      .get('situations')
      .then((situation) => setSituations(situation.data.data))
      .catch((error) => toast.error('Error'));
  }, [visible]);
  /* RESET FORM TO POPULATE WITH FETCHED DATA */
  useEffect(() => reset(data), [visible]);

  return (
    <Dialog open={visible}>
      <FormProvider {...methods}>
        <DialogContent>
          <ComboBox
            name="situation_id"
            label="Situação"
            options={situations.map((item) => ({
              id: item.id,
              text: item.description
            }))}
          />
        </DialogContent>
      </FormProvider>
    </Dialog>
  );
};
export default Modal;

ComboBox 组件:

const ComboBox: React.FC<ComboProps> = ({name, options, ...props}) => {
  const {control, getValues} = useFormContext();

  return (
    <Controller
      name={`${name}`}
      control={control}
      render={(props) => (
        <Autocomplete
          {...props}
          options={options}
          getOptionLabel={(option) => option.text}
          getOptionSelected={(option, value) => option.id === value.id}
          defaultValue={options.find(
            (item) => item.id === getValues(`${name}`)
          )}
          renderInput={(params) => (
            <TextField
              variant="outlined"
              {...props}
              {...params}
            />
          )}
          onChange={(event, data) => {
            props.field.onChange(data?.id);
          }}
        />
      )}
    />
  );
};

export default ComboBox;

我认为你在这里简化了一些事情:

  • 有条件地渲染<Modal />组件,这样您就不必在不使用它时渲染它。
  • 你不应该为你的<Autocomplete />组件设置默认值,因为 RHF 会为你管理defaultValue 因此,如果您正在重置表单,RHF 将使用该控件的新值。
  • 仅使用其中一个获取的选项作为<Autocomplete />的当前/默认值要容易得多 - 因此每次发生更改时都不会迭代所有选项(并将 situation_id 作为此控件的值传递) ,只需在获取情况后找到默认选项并使用此值重置表单即可。 在 CodeSandbox 中,我将您的控件从“situation_id”重命名为“situation”。 这样你只需要 map "situation_id" 在<Modal />的第一次渲染上,就在你将编辑的值发送到你的 api 之前保存。

我做了一个小的 CodeSandbox 试图重现你的用例,看看:

mui@v4

编辑 React Hook 表单 - NestedValue(分叉)

mui@v5

编辑 React Hook 表单 - NestedValue MUI-v5

另一件重要的事情:只有当你有深度嵌套的控件时,你才应该使用useFormContext ,否则只需将控件传递给你的<ComboBox />组件。 与使用FormProvider一样,如果表单变得更大和更复杂,它可能会影响应用程序的性能。 文档中:

React Hook Form 的 FormProvider 建立在 React 的 Context API 之上。它解决了数据通过组件树传递的问题,而无需在每一层都手动传递 props。 这也会导致组件树在 React Hook Form 触发 state 更新时触发重新渲染

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM