网站搜索

reactjs - 基于表单值的 Formik 条件验证


我有一个稍微复杂的表单。它基于我发起的 HTTP 请求类型有 3 种基本类型 (POST_USER, PUT_USER, PUT_PASSWORD)。此外,在 (POST_USER) 的情况下,我需要选择我想创建的用户类型。在 (BASIC & NON_BASIC) 之间选择。

我正在使用 React、Formik 和 Yup 进行验证。基于 HTTP_REQUEST 的验证工作得非常完美。

问题是我想根据表单的值进行检查,而我使用的来自 Formik 的 ValidationSchema 并没有将它们作为属性传递。所以,我无法向通过 ValidationSchema 传递的验证函数传递参数。这里是我用于 validationSchema 的函数。

export const VALIDATION_RULES = (execMode: executionMode): any => {
  switch (execMode) {
    case executionMode.PUT_USER:
      return Yup.object().shape({
        username: Yup.string()
          .trim()
          .required('Name is required'),
        email: Yup.string()
          .email()
          .nullable(),
        groups: Yup.array().required('Group is required')
      });
    case executionMode.PUT_PASSWORD:
      return Yup.object().shape({
        password: Yup.string()
          .trim()
          .required('Password is required'),
        confirmPassword: Yup.string()
          .trim()
          .required('Password confirmation is required')
          .oneOf([Yup.ref('password')], 'Passwords do not match')
      });
    default:
      return Yup.object().shape({
        type: Yup.mixed()
          .oneOf([AuthenticationType.BASIC, AuthenticationType.NON_BASIC])
          .required('Authentication Type is required'),
        username: Yup.string()
          .trim()
          .required('Name is required'),
        email: Yup.string()
          .email()
          .nullable(),
        password: Yup.string()
          .trim()
          .required('Password is required'),
        confirmPassword: Yup.string()
          .trim()
          .required('Password confirmation is required')
          .oneOf([Yup.ref('password')], 'Passwords do not match'),
        groups: Yup.array().required('Group is required')
      });
  }
};

executionMode 是一个简单的枚举。我在上面的函数以及组件本身中都使用它:

enum executionMode {
  POST_USER = 'POST_USER',
  PUT_USER = 'PUT_USER',
  PUT_PASSWORD = 'PUT_PASSWORD'
}

export default executionMode;

这是我的组件,我在其中调用了 Formik 本身:

      <Formik
        initialValues={this.getDefaultValues(Mode)}
        validationSchema={VALIDATION_RULES(Mode)}
        onSubmit={this.handleSubmit}
        render={({ isSubmitting, values, status }) => (
          <Form>
            ..Form Related Code. Doesn't have anything to do with validation
          </Form>
        )}
      />

问题:如上代码所述的验证,在所有场景中都能完美工作,唯独在非基本的 POST_USER 表单中有问题。问题在于,它不允许我创建用户,因为密码和确认密码的验证依然存在于验证模式(validationSchema)中。

可能的解决方案:\n1. 我尝试使用 Formik 的 validate,它会将 values 作为 props 传入,但将错误映射到 values 的逻辑需要重写,这让人很失望。除此之外,我还需要编写一些自定义代码,比如在 onChange 和 onBlur 时处理错误,而 validateSchema 则可以完美地自动处理这些。\n2. 我也尝试过使用 yup 的 when。它不起作用。表单验证通过,表单提交,但返回服务器错误。

如果你能帮忙,我将不胜感激。请不要将其标记为重复。这并不像使用when那么简单,而且在线上关于如何使用validate以及我需要如何处理事件的错误映射和处理更改的文档非常有限。感谢你的时间。