Joi 表单验证:删除显示的错误

Joi form validation: removing displayed errors

Here is a link to codesandbox example (Svelte)。它代表一个用 Joi 验证的普通寄存器。我面临的问题是清除 Joi 验证错误消息。我将它们记录在 errors 对象中,键由输入名称命名(emailpasswordpasswordConfirm)。

通过附加到表单的函数进行验证 on:input

      const validate = async e => {
        const fields = { [e.target.name]: e.target.value };
        try {
          errors[Object.keys(fields)[0]] = null;
          await registerSchema.validateAsync(
            { ...fields },
            { abortEarly: false, allowUnknown: true }
          );
        } catch (err) {
          errors[Object.keys(fields)[0]] = err;
        }
      };

它很粗糙,但大部分 都有效。它可以清除 emailpassword 错误,但无论我做什么 passwordConfirm 仍然存在。

我认为问题不在于我的 Joi 架构:

export const registerSchema = Joi.object({
  email: Joi.string().email({ tlds: { allow: false } }),
  password: Joi.string().pattern(new RegExp("^[a-zA-Z0-9]{6,30}$")).trim(),
  passwordConfirm: Joi.string().valid(Joi.ref("password")).trim()
});

我很确定这个 bug 隐藏在 validate 函数本身的某个地方,但是——我死了——我能找到它。我会很感激这里的一些提示。

Again, example can be seen on codesandbox.

您的问题确实出在您的验证函数中。当你构建你的 fields 对象时,你添加到它的唯一键是当前活动的输入: const fields = { [e.target.name]: e.target.value };,这意味着当您在架构中比较 passwordConfirmJoi.ref('password') 时,后者始终为空值,因为正在验证的对象中没有 password 键!

一种(粗略的)解决方法是确保在活动输入为 passwordConfirm:

时将 password 字段传递到正在验证的对象中
  const validate = async e => {
    const fields = { [e.target.name]: e.target.value };
    if (e.target.name === 'passwordConfirm') {
      fields.password = password;
    }
    // console.log(fields); // log object being validated
    try {
      errors[Object.keys(fields)[0]] = null;
      await registerSchema.validateAsync(
        { ...fields },
        { abortEarly: false, allowUnknown: true }
      );
    } catch (err) {
      errors[Object.keys(fields)[0]] = err;
    }
  };

已在您的 CodeSandbox 中测试,似乎按预期工作。