首页 > 解决方案 > 是的,当嵌套对象内的条件时

问题描述

所以我在使用 yup 进行条件验证时遇到问题。基本上我希望在未切换复选框时运输具有所需的属性。我正在使用 yup 的when功能,但我不知道如何从该嵌套对象中引用sameShippingAsBilling布尔值。shipping

当复选框为假时,一切正常,显示错误...但是当复选框被选中时,我收到此错误:"Cannot use 'in' operator to search for 'default' in undefined"

问题是is回调中的值未定义。when是否甚至可以从这些嵌套对象中访问外部变量。有什么替代方法可以做到这一点?

这是沙盒示例

const schema = Yup.object({
  sameShippingAsBilling: Yup.bool(),
  billing: Yup.object({
    line1: Yup.string().required(),
    city: Yup.string().required(),
    country: Yup.string().required()
  }),
  shipping: Yup.object({
    line1: Yup.string().when("sameShippingAsBilling", {
      is: !val || val === false,
      then: Yup.string().required(),
    }),
    city: Yup.string().when("sameShippingAsBilling", {
      is: !val || val === false,
      then: Yup.string().required(),
    }),
    country: Yup.string().when("sameShippingAsBilling", {
      is: !val || val === false,
      then: Yup.string().required(),
    })
  })
});

const addrValues = { line1: "", city: "", country: "" };

const formOpts = {
  mode: "onChange",
  reValidateMode: "onChange",
  defaultValues: {
    sameShippingAsBilling: true,
    billing: { ...addrValues },
    shipping: { ...addrValues }
  },
  resolver: yupResolver(schema)
};

export default function CheckoutForm() {
  const methods = useForm(formOpts);
  const { watch } = methods;

  const shippingAsBilling = watch("sameShippingAsBilling");

  const onSubmit = async (data) => {
    console.log(data);
  };

  return (
    <MuiThemeProvider theme={createMuiTheme()}>
      <FormProvider {...methods}>
        <form onSubmit={methods.handleSubmit(onSubmit)} noValidate>
          <pre>errors: {JSON.stringify(methods.errors, null, 2)}</pre>

          <div className="group">
            <FormTextField name="billing.line1" />
            <FormTextField name="billing.city" />
            <FormTextField name="billing.country" />
          </div>

          <div>
            <FormCheckbox name="sameShippingAsBilling" />
          </div>

          {!shippingAsBilling && (
            <div className="group">
              <FormTextField name="shipping.line1" />
              <FormTextField name="shipping.city" />
              <FormTextField name="shipping.country" />
            </div>
          )}

          <div>
            <button type="submit">Pay</button>
          </div>
        </form>
      </FormProvider>
    </MuiThemeProvider>
  );
}

标签: javascriptreactjsyupreact-hook-form

解决方案


您可以shipping根据值有条件地渲染对象的形状sameShippingAsBilling

这些方面的东西:

sameShippingAsBilling: Yup.bool(),
shipping: Yup.object().when("sameShippingAsBilling", {
    is: (sameShippingAsBilling) => !sameShippingAsBilling,
    then: Yup.object().shape({
      line1: Yup.string().required(),
      city: Yup.string().required(),
      country: Yup.string().required(),
    }),
    otherwise: Yup.object().shape({
      line1: Yup.string(),
      city: Yup.string(),
      country: Yup.string(),
    }),
  }),

推荐阅读