Formik 的自定义 "dirty" 逻辑

Custom "dirty" logic for Formik

我有一个用 React 和 Formik 制作的应用程序。我正在尝试为用户添加一个警告,让他们在离开之前保存更改。从 react-router-dom 5 开始,我们可以使用 Prompt。因此,我的初始代码是:

const PromptWhenDirty = () => {
  const { dirty, touched } = useFormikContext();
  console.log('touched:', touched);
  return <Prompt when={dirty} message={'Leave without saving changes?'} />;
};

我在基于 formik 的“步骤向导”中添加了一行,现在它看起来像:

  <Form>
    <PromptWhenDirty />
    <Step
      current={currentStep}
      values={values}
      onChange={onChange}
      handleSubmit={handleSubmit}
      errors={errors}
      isSubmitting={isSubmitting}
    />
  </Form>

提示对话框确实出现了,并且工作正常。但是,对于某些步骤,我的 dirty 标志始终设置为 true。我不确定为什么。我确实利用了 useField 和许多其他功能。我假设 dirty 可能在 [某些] 我的步骤字段初始化期间以某种方式设置。

此外,在我按下提交一次之前 [-这是一个步骤向导,其中的数据在每个步骤中都会重新提交],总是 {}。编辑字段数据不会设置它。第一次提交表单后,表单中的每个字段都在 touched 中并设置为 true.

我觉得 dirty 只是在 onChange 中设置为:

const onChange = (props) => {
  console.log('set dirty here');
  ...
}

我知道我可以使用状态挂钩,并将其设置在 onChange 中。但是,我的印象是将 Formik 与状态混合是一个坏主意,因此添加了 useField

我可以覆盖 dirty 的计算方式吗?

我最终做了以下事情:

useEffect(() => {
  // initialization is compete, reset `dirty`
  if (mask.value) {
    resetForm({
      values: {
        ...values,
        mask: mask.value,
        croppedImage: croppedImage.value
      }
    });
  }
  // eslint-disable-next-line
}, [mask.value]);

这不是一个完美的解决方案。对掩码的更改不会弄脏,更糟的是会重置它。然而,它比以前好得多。另外,挂钩位于其中一个台阶内。其他步骤没有初始化问题,不需要重新设置脏。我试图连接到我的裁剪器组件的 onReady 方法。然而,结合 formik useField,我无法轻易让它工作。