如何使用 React/Formik 和 Yup 验证将此对象嵌套在另一个对象中?

How can I nest this Obejct inside another using React/Formik and Yup validation?

我正在尝试学习如何使用 Formik 和 Yup 来验证输入(文本)表单域。我遵循了 Jared Palmer 的标准方法,开箱即用,效果很好。

当涉及到做更多组件驱动的事情时,我很难达到相同级别的验证,而且我无法弄清楚我哪里出错了?

是的,似乎无法识别我的表单模型,也不会按要求验证输入字段...

我在想我实际上搞砸了初始值,或者我没有以 Yup 正在寻找的正确形状提供它们,但是这里的任何帮助都会很棒,这让人发疯.. .

我有一个示例沙箱,运行 这里 > >

https://codesandbox.io/s/building-multi-step-form-with-formik-yup-vjzpk

表单模型 (components/CheckoutPage/FormModel/checkoutFormModel.js):

export default {
  formId: "checkoutForm",
  formField: {
    nestedObj: {
      firstName: {
        name: "firstName",
        label: "First name*",
        requiredErrorMsg: "First name is required"
      }
    }
  }
};

初始值 (components/CheckoutPage/FormModel/initialValues.js):

import checkoutFormModel from "./checkoutFormModel";
const {
  formField: {
    nestedObj: { firstName }
  }
} = checkoutFormModel;

export default {
  nestedObj: {
    [firstName.name]: ""
  }
};

是的验证模式 (components/CheckoutPage/FormModel/validationSchema.js):

import * as Yup from "yup";
import checkoutFormModel from "./checkoutFormModel";
const {
  formField: {
    nestedObj: { firstName }
  }
} = checkoutFormModel;

export default [
  Yup.object().shape({
    nestedObj: Yup.object().shape({
      [firstName.name]: Yup.string().required(`${firstName.requiredErrorMsg}`)
    })
  })
];

结合了 Yup 和 Formik 的地址表 (components/CheckoutPage/Forms/AddressForm.js):

import React from "react";
import { Grid } from "@material-ui/core";
import { InputField } from "../../FormFields";

export default function AddressForm(props) {
  const {
    formField: {
      nestedObj: { firstName }
    }
  } = props;
  return (
    <React.Fragment>
      <Grid container spacing={3}>
        <Grid item xs={12} sm={6}>
          <InputField name={firstName.name} label={firstName.label} fullWidth />
        </Grid>
      </Grid>
    </React.Fragment>
  );
}

会发生什么,你的 yup 验证将验证像

这样的对象
{
    nestedObj: {
        [firstName.name]: '' // Validation will get here
    }
}

但是当你传递给你的输入时 name={firstName.name} 你的输入会像

{
    [firstName.name]: ''
}

所以你错过了验证,因为你在 yup 验证中添加了 nestedObj

您忘记将 nestedObj 添加到 firstName.name

因此,您可以将验证架构更改为

Yup.object().shape({
  [firstName.name]: Yup.string().required(`${firstName.requiredErrorMsg}`)
})

传递给输入,名字nestedObj

<InputField name={`nestedObj.${firstName.name}`} label={firstName.label} fullWidth />

您可以选择将其作为道具或硬编码字符串传递。