网站搜索

javascript - Formik 嵌套初始值、表单字段名称和点符号表示法?


TL;DR

在 Formik 中,如果我有一个用点表示法写的字段名(例如 name="hands.left"),它链接到 initialValues 中嵌套对象的一个属性(例如 hands: {left: " ", right: " "}),在使用验证错误时,我该如何使用该字段名,也就是访问对象属性(errors.hands.left 和 errors["hands.left"] 都不起作用)?

由于我扩展的 Typescript 接口定义,我有一个带有嵌套 initialValues 的动态 Formik 表单,例如:

<Formik
  initialValues={{
    description: "",
    specialist: "",
    discharge: {
      date: "",
      criteria: "",
    },
// ...

附加在嵌套值(出院日期和出院标准)上的表单字段如下所示:

          <Field
            name="discharge.date"
            component={TextField}
          />

我使用点符号,因为这似乎是将字段与我的初始值关联的唯一方法,这样当输入文本时,initialValue discharge.date(即 initialValues 中 discharge 对象的 date 属性)会被修改。

但是我的问题出现在添加 Formik 验证时:

validate={(values) => {    
          const requiredError = "Field is required";
          const errors: { [field: string]: string } = {};   

          if (!values.discharge.date) {
            errors.discharge.date = requiredError;
          }
          // ...

如果我尝试像那样使用点符号访问错误(errors.discharge.date),我会收到一个警告,提示“类型 'string' 上不存在属性 'date'”。

我的解决方法是将字段名从“discharge.date”改为“dischargeDate”:

      <Field
        name="dischargeDate"
        component={TextField}
      />

和

      if (!values.discharge.date) {
        errors.dischargeDate = requiredError;
      }

这对错误对象有效,但会使字段与我的初始值(discharge>date)断开连接,所以当我在字段中输入文本时,不会更改嵌套对象值(discharge.date)的状态,而是创建了一个新的单独变量“dischargeDate”:

在命名字段以同时访问嵌套的 initialValue(initialValues>discharge>date)和错误对象属性(errors.discharge.date)时,我应该怎么做?唯一的解决办法是重命名我的 TypeScript 类型吗?

interface BaseEntry {
  description: string;
  specialist: string;
}

interface Discharge {
  date: string;
  criteria: string;
}

export interface HospitalEntryType extends BaseEntry {
  discharge: Discharge;
}

答案#1

import { FormikErrors } from 'formik';

interface BaseEntry {
  description: string;
  specialist: string;
}

interface Discharge {
  date: string;
  criteria: string;
}

export interface HospitalEntryType extends BaseEntry {
  discharge: Discharge;
}

interface FormValues extends HospitalEntryType {}

validate = (values: FormValues) => {
  let errors: FormikErrors<FormValues> = {};
  const requiredError = "Field is required";
  
  if (!values.discharge.date) {
    errors = { 
      discharge: {
        date: requiredError
      }
    }
  }

  return errors;
}