React Formik - 在组件重新安装和启用按钮上验证表单

blu*_*l2k 6 javascript reactjs formik

我正在编写一个 React 应用程序并使用 Formik 和 Yup 作为表单。我遇到问题的页面是一个向导样式的页面,它在页面加载时呈现 Form1,上面有一个“下一步”按钮。按“下一步”呈现 Form2,并且“返回”和“下一步”按钮与 Form2 一起出现,这将引导您完成向导。

问题在于使用“后退”按钮。完成 Form1 的填写后,“下一步”按钮变为启用状态,我可以移动到下一个表单。当我在 Form2 上时,我希望能够返回到 Form1 并按“返回”按钮。当 Formik 重新渲染时,它会将值正确加载到表单中,但它不会验证表单,因此“下一步”按钮被禁用,即使数据有效。我必须在其中一个字段上引发更改事件才能启用“下一步”按钮。

在这种情况下,当表单重新呈现时,应启用“下一步”按钮。我浏览了文档并尝试了 Formik 中的 validateOnMount 道具,它的名字应该可以工作。文档建议使用 initialErrors,但我不清楚如何使用它。问题也可能是我如何启用/禁用“下一步”按钮。

这已经让我发疯了好几个小时,并且是在周五下午完成此页面的最后一件事。

<Formik
     enableReinitialize
     validationSchema={validationSchema}
     initialValues={initialValues}
     validateOnMount
     render={({ isValid, values, isSubmitting, handleChange, setFieldValue, setFieldTouched }) => (
         <Form className="text-center">
            <FieldRow labelName="What's your address? (Can't be a PO Box)">
                <AddressField
                   id="address"
                   name="address"
                   data-testid="address"
                   onChange={handleChange}
                   onBlur={setFieldTouched}
                   values={values}
                   setFieldValue={setFieldValue}
                   validateForm={validateForm}
                /> </FieldRow>
               <div className="mt-5">
                  <Button
                    data-testid="submit-next"
                    color="primary"
                    onClick={() => handleNext(values)}
                    className="float-right"
                    disabled={isValid === false || isSubmitting}
                 >
                    {isSubmitting ? <Spinner /> : 'Next'}
                 </Button>
                 <Button
                    data-testid="submit-back"
                    color="light"
                    onClick={() => handleBack()}
                    className="float-left"
                    disabled={true}
                  >
                    Back
                  </Button>
              </div>
          </Form>
      )}
/>
Run Code Online (Sandbox Code Playgroud)

Dan*_*ger 3

这不起作用的原因是因为当您第一次访问该页面时,Formik组件已安装并呈现。然后,当您按下一步或返回时,它不会再次安装,它只是更新,因此不会再次触发验证。

如果您有后退和下一步按钮,我假设您使用它们来增加index或step变量/状态。validateForm()您可以做的是从状态useEffect为 的手动触发验证调用。stepdeps

为此,您必须替换<Formik render={...} />为 <Formik component={...} />或 with useFormik,因为您不能useEffect在回调中使用,如评论中所指出的。使用第二种选择:

const {
  isValid,
  values,
  isSubmitting,
  handleChange,
  setFieldValue,
  setFieldTouched,
  validateForm,
} = useFormik({
  initialValues,
  enableReinitialize,
  validationSchema,
})

useEffect(() => {
  // This will be called everytime `step` changes:
  validateForm();
}, [step]);

return (
  <Form ...>
    ...
  </Form>
);
Run Code Online (Sandbox Code Playgroud)

或者,您可以尝试使用initialErrors,但这可能会在实际上不需要这样做时触发验证,如果除此之外还有其他原因step可能导致重新渲染:

<Formik
  initialErrors={ validationSchema.isValidSync(initialData) }
  ...
/>
Run Code Online (Sandbox Code Playgroud)

另外,看起来目前存在一个相关的错误,并且建议的临时修复也在使用useEffect,因此即使您选择initialErrors,您可能仍然需要添加useEffect,直到解决此问题:

https://github.com/jaredpalmer/formik/issues/1950