简体   繁体   English

如何在 TS React 中使用 Joi 验证两个密码字段?

[英]How to validate two password fields with Joi in TS React?

I am building a reusable form component with TypeScript, let's call it AbstractForm for now.我正在用 TypeScript 构建一个可重用的表单组件,现在我们称之为AbstractForm It is designed to be inherited by other components like LoginForm , RegisterForm and so on, let's say I am working on some DerivedForm component.它被设计为由其他组件(如LoginFormRegisterForm等)继承,假设我正在处理一些DerivedForm组件。 To validate the fields I am using Joi .为了验证我使用的字段Joi The derived component only has to supply the domain model (Joi validation schema) and the submit method.派生组件只需要提供域模型(Joi 验证模式)和提交方法。
Everything works great and validates perfectly, except when I want to use two password fields, and the second password is checked to match the first one via Joi.string().valid(this.state.data.password) .一切都运行良好并且验证完美,除非我想使用两个密码字段,并且通过Joi.string().valid(this.state.data.password)检查第二个密码以匹配第一个密码。 It never passes the validation even when both passwords are identical, Joi still throws an error saying that they are not.即使两个密码相同,它也永远不会通过验证,Joi 仍然抛出一个错误,说它们不是。 And I can't even think of a reason why.我什至想不出原因。 Can someone suggest what is the cause of this behaviour?有人可以建议这种行为的原因是什么?
I am not using Joi.ref('password') instead because fields are validated in isolation with every onChange event (method validateProperty() in AbstractForm does it).我没有使用Joi.ref('password')而是因为字段是通过每个onChange事件Joi.ref('password') validateProperty() AbstractForm中的validateProperty()方法是这样做的)。

This is the Schema interface defined in the AbstractForm module:这是AbstractForm模块中定义的 Schema 接口:

export interface Schema {
  [key: string]: Joi.Schema;
}

This is my schema in the DerivedForm :这是我在DerivedForm中的DerivedForm

schema: Schema = {
name: Joi.string()
  .required()
  .min(1)
  .label('Name'),
email: Joi.string()
  .required()
  .email()
  .min(5)
  .label('Email'),
password: Joi.string()
  .required()
  .min(8)
  .label('Password')
  .error(
    errors => 'Passwords should match and have at least 8 characters.'
  ),
repeatPassword: Joi.string()
  .valid(this.state.data.password)
  .required()
  .label('Password')
  .error(
    errors => 'Passwords should match and have at least 8 characters.'
  ),
};

And this is how these fields are validated inside the AbstractForm :这就是在AbstractForm中验证这些字段的方式:

validateProperty = (name: string, value: string) => {
  const property = { [name]: value };
  const propSchema: Schema = { [name]: this.schema[name] };
  const { error } = Joi.validate(property, propSchema);
  return error ? error.details[0].message : null;
};

handleChange = (e: ChangeEvent<HTMLInputElement>) => {
  const { name, value } = e.currentTarget;

  const data = { ...this.state.data };
  data[name] = value;

  const errors = { ...this.state.errors };
  const errorMessage = this.validateProperty(name, value);
  if (errorMessage) errors[name] = errorMessage;
  else delete errors[name];

  this.setState({ data, errors });
};

I am also aware that this.setState() as well as the new useState() calls are asynchronous, but we are talking about validating against a different field here, so it should not be a problem.我也知道this.setState()以及新的useState()调用是异步的,但我们在这里讨论的是针对不同的字段进行验证,所以这应该不是问题。
I can add all the code for both modules if needed.如果需要,我可以添加两个模块的所有代码。 Thanks in advance!提前致谢!

It turns out that the valid reference to the first password field is generated only when the component is mounted.事实证明,只有在安装组件时才会生成对第一个密码字段的有效引用。 To update the reference, you can add this piece of code:要更新参考,您可以添加以下代码:

  componentDidUpdate() {
    this.schema.repeatPassword = Joi.string()
      .min(8)
      .valid(this.state.data.password)
      .required()
      .label('Password')
      .error(
        errors => 'Passwords should match and have at least 8 characters.'
      );
  }

...so it could remember the new "valid" value. ...所以它可以记住新的“有效”值。 I think that this is happening because I am using class component, not functional component.我认为这是因为我使用的是类组件,而不是功能组件。 And with functional component the schema would update every render by itself.对于功能组件,架构将自行更新每个渲染。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM