【问题标题】:React formik form validation: How to initially have submit button disabledReact formik 表单验证:如何最初禁用提交按钮
【发布时间】:2020-04-14 00:22:13
【问题描述】:

下面是我使用formikReact 表单验证代码。默认情况下,当表单加载时,我希望禁用提交按钮:

import { useFormik } from "formik";
import * as Yup from "yup";

const formik = useFormik({
    initialValues: {
      firstName: "",
      lastName: "",
      email: ""
    },
    validationSchema: Yup.object({
      firstName: Yup.string()
        .max(15, "Must be 15 characters or less")
        .min(3, "Must be at least 3 characters")
        .required("Required"),
      lastName: Yup.string()
        .min(3, "Must be at least 3 characters")
        .max(20, "Must be 20 characters or less")
        .required("Required"),
      email: Yup.string()
        .email("Invalid email address")
        .required("Required")
    }),
    onSubmit: values => {
      handleSubmit(values);
    }
  });

我尝试在我的按钮上使用它:

 disabled={!formik.isValid}

但只有在我尝试提交表单时它才会真正起作用。因此,如果我将表单留空并点击提交,则会显示所有验证错误,然后该按钮被禁用。但是,它应该从一开始就被禁用。我检查了documentation,但没有看到任何明显的东西。

【问题讨论】:

    标签: reactjs validation formik yup


    【解决方案1】:

    如果您想在表单加载时保持submit 按钮最初处于禁用状态,您可以使用Formikdirty : boolean 属性,如下所示:

    disabled={!formik.dirty}
    

    如果您想保持submit 按钮处于禁用状态,直到所有字段值都有效,那么您可以使用isValid: boolean,其工作原理如下:

    如果没有错误(即错误对象为空)返回 true,否则返回 false。

    所以你可以把它用作:

    disabled={!formik.isValid}
    

    现在,如果您希望在所有字段都有效之前禁用提交按钮,并且如果字段值已从其初始值更改,那么您必须使用上述两个属性结合如下:

    disabled={!(formik.isValid && formik.dirty)}
    

    【讨论】:

    • 谢谢,这几乎可行,但不完全。当页面首次加载时,该按钮被禁用。但是,只要一个文本字段正确,按钮就会启用。只有在所有字段都正确填写后才会发生这种情况。
    • 我已经编辑了我的答案并添加了一些更有用的代码。请让我知道这是否有效,如果对您有帮助,请考虑接受我的回答:)
    • 如果有一些有效的初始值,按钮将永远不会被启用。
    • 正如@SashaOmelchenko 指出的那样,这不会验证initialValues。将validateOnMountisValid 一起使用。见stackoverflow.com/a/61896771/1631828
    • 我就是这样做的,但是 isValid 在每种类型的键盘之后都会切换真/假。有人也遇到这个问题吗?
    【解决方案2】:

    要使按钮最初被禁用,只需检查触摸对象是否为空并保持这种状态,直到所有字段都通过!isValid 验证

    disabled={!isValid || (Object.keys(touched).length === 0 && touched.constructor === Object)}
    

    【讨论】:

      【解决方案3】:

      Formik 会跟踪字段值和错误,但会公开它们以供您使用,这曾经是通过 formProps 使用渲染道具模式完成的,但现在似乎是 useFormik 钩子返回的 formik 变量的一部分。

      我建议首先将初始值删除为常量。然后你需要访问formik的错误对象。我没有使用新的钩子语法做到这一点,但是,查看文档我希望“formik.errors”可以工作(这在 formProps.errors 中使用渲染道具公开)。最后,禁用提交按钮应该是检查 formik.values 是否等于初始值或错误对象不为空。

      【讨论】:

        【解决方案4】:

        您可以添加validateOnMount并将其设置为true

        const formik = useFormik({
            initialValues: {
              validateOnMount: true, // <================= Add this
              firstName: "",
              lastName: "",
              email: ""
            },
            validationSchema: Yup.object({
              firstName: Yup.string()
                .max(15, "Must be 15 characters or less")
                .min(3, "Must be at least 3 characters")
                .required("Required"),
              lastName: Yup.string()
                .min(3, "Must be at least 3 characters")
                .max(20, "Must be 20 characters or less")
                .required("Required"),
              email: Yup.string()
                .email("Invalid email address")
                .required("Required")
            }),
            onSubmit: values => {
              handleSubmit(values);
            }
          });
        

        在按钮上使用

        disabled={!formik.isValid}

        【讨论】:

          【解决方案5】:

          我正在使用

          "formik": "^2.2.6"

          就我而言,我是这样做的。我对在初始验证消息中显示消息不感兴趣,所以我这样做了。

          我正在使用基于类的组件

          <Formik
          ......
          validateOnBlur={true}
          validateOnChange={true}
          
          {({handleChange, values, touched, errors, handleBlur }) => (<>
              ..........
              <Form.Control
                  placeholder="Name"
                  type="text"
                  name="field_dba"
                  value={values.name}
                  onChange={handleChange}
                  onFocus={handleBlur} // It plays a role to change the touched property 
                  isInvalid={touched.name && !!errors.name}
                  isValid={!errors.name}
                  className="form-input"
              />
              <label className="modal-lab">Name *</label>
              // Here i'm checking the field is touched or not 
              {touched.name ? <Form.Control.Feedback type="invalid" className="text-capitalize"> {errors.name} </Form.Control.Feedback> : null}
          

          最后禁用按钮,直到它全部被验证。我正在使用这个

          <button disabled={Array.isArray(errors) || Object.values(errors).toString() != ""} type="submit"> Submit </button>
          

          如果这适用于相同的版本,请点赞。

          【讨论】:

            猜你喜欢
            • 2020-08-28
            • 2020-09-21
            • 1970-01-01
            • 2022-10-24
            • 2015-06-24
            • 1970-01-01
            • 2021-03-08
            • 2019-11-06
            • 1970-01-01
            相关资源
            最近更新 更多