是的/使用动态密钥进行 Formik 验证

Gol*_*ket 9 typescript reactjs yup formik

我正在尝试验证具有动态数量字段的表单 - 即,数据从确定显示多少行的 API 返回,并且对于每一行,都有一个必填字段,需要用户为他们选择一个输入进步。

要使用的软件包是 Yup 和 Formik 一起使用。在查看 Yup 教程时,该对象通常是按如下方式构建的:

let userSchema = object({
  name: string().required(),
});
Run Code Online (Sandbox Code Playgroud)

定义名称等键的位置。但是,我的密钥需要是动态的,即 field1、field2 等,因为我事先不知道会有多少个。

我想循环遍历我的对象并将一组动态键传递给模式 - 基本上,无论对象有多长,我都有多少个键。

let userSchema = object({
  [field1]: string().required(),
  [field2]: string().required(),
});
Run Code Online (Sandbox Code Playgroud)

但是,我不确定如何实现这个结果。我可以循环遍历我的对象并尝试构建一组键,例如

let myObject = {}
myKeyObject.forEach((key) => myObject[key] = string().required());
Run Code Online (Sandbox Code Playgroud)

然后传递myKeyObject给object.shape,但这通常会产生TS错误。有谁知道 Yup 中有任何用于动态表单的实用程序吗?除非我遗漏了某些内容,否则我在文档中没有看到任何可以使使用动态表单变得更容易的内容

Oss*_*ili 8

如果您想要动态字段,您可以添加一个字段数组(包含字段或键的名称、标签、初始值和字段类型),然后从该数组生成一个架构,下面是一个示例:

import React, { Fragment } from 'react';
import { Field, Form, Formik } from 'formik';
import { string, object, number } from 'yup';

interface IField{
  name: string,
  label: string,
  initialValue: any,
  type: any
}

const fields: IField[] = [
  {
    name: 'firstName',
    label: 'Firstname',
    initialValue: '',
    type: string().required()
  },
  {
    name: 'lastName',
    label: 'Lastname',
    initialValue: '',
    type: string().required()
  },
  {
    name: 'email',
    label: 'Email',
    initialValue: '',
    type: string().required()
  },
  {
    name: 'password',
    label: 'Password',
    initialValue: '',
    type: string().required()
  },
  {
    name: 'age',
    label: 'Age',
    initialValue: 18,
    type: number()
  }
];

const initialValues = Object.fromEntries(fields.map((field)=>[field.name, field.initialValue]))

const SchemaObject = Object.fromEntries(fields.map((field)=>[field.name, field.type]))

const UserSchema = object().shape(SchemaObject);

const App = () => (
  <Fragment>
    <h1>User</h1>
    <Formik
      initialValues={initialValues}
      onSubmit={values =>
        console.log({values})
      }
      validationSchema={UserSchema}
      >
        {({ errors, touched }) => {
          return(
          <Form>
            <div>
               {fields.map(({label, name}, index) => (
                  <div key={index}>
                    <label style={{width: 100, display: 'inline-block'}}>{label}</label>
                    <Field name={name} />
                    {touched[name] && errors[name] && <div style={{color: 'red'}}>{errors[name]?.toString()}</div>}
                  </div>
                ))}
              <div>
                <button type="submit">Submit</button>
              </div>
            </div>
        </Form>
      );
      }}
    </Formik>
  </Fragment>
);

export default App;
Run Code Online (Sandbox Code Playgroud)