用 yup 进行条件验证

conditional validation with yup

我在一个表单中有 3 个字段,“类型”字段是 select 并且从该列表中,一些项目启用或禁用“输出”字段,如果启用我需要“输出”字段小于“in”字段,反之亦然,但如果“out”字段被禁用,我不需要验证,我正在尝试使用 .when,但没有工作,关于如何做的任何想法这个?

  const [disableOutCounterField, setDisableOutCounterField] = useState(false);

  const schema = yup.object().shape({
    type: yup.string().required(requiredMessage),
    in: yup
      .number(numberMessage)
      .required(requiredMessage)
      .integer(integerMessage)
      .min(1, positiveMessage)
      .typeError(numberMessage)
      .when("out", {
        is: !disableOutCounterField,
        then: yup.number().moreThan(yup.ref("out"), moreThanMessage),
        message: moreThanMessage,
      }),
    out: yup
      .number(numberMessage)
      .integer(integerMessage)
      .typeError(numberMessage)
      .lessThan(yup.ref("in"), lessThanMessage),
  });

结构:

.when("out", {
  is: !disableOutCounterField,

out 值与 !disableOutCounterField 进行比较,如果它们相等,则应用 then 规则。但很可能它们永远不会相同。

此处需要的检查只是 !disableOutCounterField 本身的值,对于 out 的任何值。这可以使用表达式来完成:

.when("out", {
  is: value => !disableOutCounterField,

换言之:对于每个 out 值,return !disableOutCounterField,如果 return 为真,则应用 then 部分。

我找到的另一种方法是从 useEffect.

中重新生成对象 validationSchema

这有使用 useState 的好处,无需提前将它们映射到特定的表单字段,例如,如果您有条件地从数据库中设置某些内容并且不想将其设置为隐藏字段某处。

const validationPiece = yup.object({
amount: yup
  .number()
  .typeError('Please enter an amount')
  .required('Please enter an amount')
});

const [validationSchema, setValidaitonSchema] = useState(yup.object({}));

const {
  register,
  handleSubmit,
  reset,
  formState: { errors },
} = useForm({
  resolver: yupResolver(validationSchema),
});

useEffect(() => {
  if (needNewPartOfForm) {
    const validationSchemaDict = {};
    if (needNewPartOfForm.xyz) {
      validationSchemaDict['xyz'] = validationPiece; // does this need a cloneDeep?
    }
    if (needNewPartOfForm.abc) {
      validationSchemaDict['abc'] = validationPiece;
    }
    setValidaitonSchema(yup.object(validationSchemaDict));
  }
}, [clientDocs, clientId, reset, teamId]);