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

k10s72fa  于 12个月前  发布在  Java
关注(0)|答案(3)|浏览(117)

我正在编写一个React应用程序,并使用Formik和Yup来处理表单。我遇到的问题是一个向导风格的页面,它在页面加载时呈现Form 1,上面有一个“Next”按钮。按下“Next”会呈现Form 2,“Back”和“Next”按钮会与Form 2一起出现,这会让你通过向导。
麻烦的是使用返回按钮。在我完成填写Form 1后,“Next”按钮变为启用,我可以移动到下一个表单。当我在Form 2上时,我希望能够返回Form 1并按下“Back”按钮。当重新呈现Formik时,它会将值正确加载到表单中,但它不会验证表单,因此“Next”按钮被禁用,即使数据是有效的。我必须在其中一个字段上引起一个更改事件才能启用“下一步”按钮。
在这种情况下,当表单重新呈现时,“Next”按钮应该被启用。我已经看过文档并尝试了Formik中的validateOnMount prop,根据它的名称应该可以工作。文档建议使用initialErrors,但我不清楚如何使用它。问题也可能是我如何启用/禁用“Next”按钮。
这让我抓狂了好几个小时,这是我在周五下午完成这一页的最后一件事。

<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>
      )}
/>

字符串

0s0u357o

0s0u357o1#

这不起作用的原因是因为当你第一次进入该页面时,Formik组件被挂载并呈现。然后,当你按下下一步或后退时,它不会再次挂载,它只是更新了,所以它不会再次触发验证。
如果你有back和next按钮,我假设你使用它们来递增indexstep变量/状态。你可以做的是从step状态为depsuseEffect手动触发验证调用validateForm()
为了做到这一点,你必须用<Formik component={...} />useFormik替换<Formik render={...} />,因为你不能在回调函数中使用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>
);

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

<Formik
  initialErrors={ validationSchema.isValidSync(initialData) }
  ...
/>


此外,看起来当前有一个相关的bug打开,建议的临时修复也使用useEffect,所以即使你使用initialErrors,你可能仍然需要添加useEffect,直到这个问题得到解决:
https://github.com/jaredpalmer/formik/issues/1950

brtdzjyr

brtdzjyr2#

我发现一个避免运行useEffect onMount的简单方法是在表单中使用onFocus prop。例如:

const [hasFocused, setHasFocused] = useState(false);

    <Formik ...>
        {({ isValid, ... }) => (
            ...
            <TextInput
                onFocus={() => setHasFocused(true)}
                ...
            />
            <Button
                type="submit"
                disabled={!isValid || !hasFocused}
                ...
            />
        }
    </Formik>

字符串
如果表单中有多个输入,只需向每个输入添加相同的onFocus={() => setHasFocused(true)
让我知道如果你有任何问题:)

wb1gzix0

wb1gzix03#

我相信在装载时进行验证并获得'isValid'的正确值的正确方法是,这对我很有效

const {
  isValid,
 } = useFormik({
   initialValues,
   validationSchema,
   enableReinitialize: true,
   validateOnMount: true,
   onSubmit: async () => {},
  });

字符串

相关问题