使用 FormProvider 时如何访问 formState.errors

How to access formState.errors when using FormProvider

我正在构建一个使用 FormProvider 的抽象“深度嵌套”表单组件。我在 field 级别进行错误验证,但我不知道如何访问 formState 级别的 errors 对象。

FormProvider docs 说“FormProvider 需要所有 useForm 方法”,示例代码变为

export default function App() {
  const methods = useForm();
  const onSubmit = data => console.log(data);

  return (
    <FormProvider {...methods} > // pass all methods into the context
    ...

我的(看似有效的)抽象表单组件如下所示:

let renderCount = 0;

function FormDialog(props) {
  const {
    open, onClose, loading, headline, noEscape, onFormSubmit, content, actions
  } = props;

  renderCount++;

  let validationSchema = YupObject().shape({});

  // construct schema
  content.forEach(item => {
    validationSchema = validationSchema.concat(YupObject().shape({
      [item.component.props.name]: item.validation
    }));
  });

  const methods = useForm({
    resolver: yupResolver(validationSchema)
  });

  return (
    <Dialog
      open={open}
      onClose={onClose}
      disableEscapeKeyDown={loading || noEscape}
    >
      <DialogTitle>{headline}</DialogTitle>
      <Box>
        Render Count: {renderCount}
      </Box>
      <FormProvider {...methods}>
        <DialogContent>
          <Box component="form" 
            sx={{
              onSubmit: methods.handleSubmit(onFormSubmit)
            }}
          >
            <FormContent content={content} />
          </Box>
          <HighlightedInformation>
          </HighlightedInformation>
        </DialogContent>
        <DialogActions>
          <FormActions actions={actions} />
        </DialogActions>
      </FormProvider>
    </Dialog>
  );
}

export default FormDialog;

像那样,它会渲染、显示“渲染计数:2”(因为我处于开发模式,因此使用 React.StrictMode)并很好地指出 field 级别的错误。但是,我不知道如何访问 formState errors 属性.

我能找到的所有示例都在初始 useForm 调用期间将 formState 拉出:

  const {
    register,
    handleSubmit,
    formState
  } = useForm();

但是,由于FormProvider,我需要将methods中的全部拉出来。明确地重组它们似乎不是一个好主意。我尝试过的各种事情:

useFormState():

  ...
  const methods = useForm({
    resolver: yupResolver(validationSchema)
  });
  
  const { errors } = useFormState();
  console.log('errors', errors);
  ...

显式传递control

  const { errors } = useFormState( methods.control );
  console.log('errors', errors);

两者都导致 TypeError: null is not an object (evaluating 'methods.control')

解构methods得到对象:

  const methods = useForm({
    resolver: yupResolver(validationSchema)
  });

  const { formState: {errors} } = methods;
  console.log('errors', errors);

包装在useEffect中,如formState docs:

中所述
  useEffect(() => {
    console.log('errors:', methods.formState.errors);
  },[methods.formState]);

后两者都会导致无限重新渲染和浏览器挂起。

那么,在使用 FormProvider 并拉出所有 methods 时,如何到达 formState errors

我更改了一些内容,现在似乎可以使用了:Codesandbox

  1. 不要将 onSubmit 作为 sx 属性传递。我认为 sx 应该只接受样式道具,不确定为什么它允许回调等。

  2. form元素包裹在提交按钮周围,否则无法提交。

  3. ConnectForm 什么也没做所以我也删除了它,但不确定它是否对错误有任何影响。