使用 Yup 访问必填字段

问题描述 投票:0回答:5

我使用react-hook-form 和 yup 来验证我的表单。

我想知道模式的所有必填字段以在表单中显示一些信息(例如必填字段的“*”)。 我们可以通过这行代码来实现这一点:

schema.describe().fields[field].tests.findIndex(({ name }) => name === 'required'

但是,此代码不适用于条件验证。

架构示例:

const schema = yup.object().shape({
    email: yup
    .string()
    .email()
    .required(),

    isProfileRequired: yup
    .boolean(),

    profile:  yup
    .object()
    .when('isProfileRequired',{
        is: (isProfileRequired) => isProfileRequired,
        then:
            yup
            .object()
            .nullable()
            .required()
    })
})

有没有办法在表单中检索这些信息?

javascript reactjs yup react-hook-form
5个回答
7
投票

实际上没有“好”的方法来做到这一点,但这很有效:

function isRequired(field){
    return schema.fields[field]._exclusive.required || false 
}

注意:如果需要或未定义,

schema.fields[field]._exclusive.required
返回 true。


5
投票

测试 ExclusiveTests 而不是 _exclusive 对我有用。

const isRequired = 
validationSchema?.fields[aField.name]?.exclusiveTests?.required || false;

2
投票

基于@colinD 共享的链接中的此评论,这对我来说效果很好。

const isFieldRequired = (validationSchema, id) =>
  validationSchema
    .describe()
    .fields[id].tests.some(({ name }) => name === 'required')

这会检查特定字段中的任何

test
是否具有等于
name
'required'
。例如:

const validationSchema: AnyObject = object({
  username: string().required(),
  email: string().email().required(),
})

将生成一个带有

fields
的模式,如下所示:

{
  username: {
    ...
    tests: [
      {name: 'required', ...}, // is required
    ]
  },
  email: {
    ...
    tests: [
      {name: 'email', ...},
      {name: 'required', ...}, // is required
    ]
  },
}


2
投票

是的

1.2.0
,现在使用的属性似乎是
optional
上的
SchemaDescription
布尔值。

这是一个返回

Record<keyof T, bool>
的函数,其中
T
是模式的通用参数,如果字段被标记为必填,则布尔值为
true
,否则为
false

import { ObjectSchema, SchemaDescription } from "yup";

type FormObject = Record<string, unknown>;

const getRequiredFields = <T extends FormObject>(
  schema: ObjectSchema<FormObject>
) => {
  const fields = schema.describe().fields as Record<keyof T, SchemaDescription>;

  return Object.entries(fields).reduce((newObj, [key, schemaDescription]) => {
    newObj[key as keyof T] = !schemaDescription.optional;
    return newObj;
  }, {} as Record<keyof T, boolean>);
};

用途:

const schema = yup.object({
  name: yup.string().required(),
  otherField: yup.string().optional(),
  code: yup.number().required(),
});

const fields = getRequiredFields(schema);

// fields = {
//    name: true,
//    otherField: false,
//    code: true,
// }


0
投票

我根据@colinD解决方案制作了一个钩子。

export const useIsFieldRequired = <T extends FormObject>(
  schema: ObjectSchema<T>,
) => {
  const getRequiredFields = () => {
    const fields = schema.describe().fields as Record<
      keyof T,
      SchemaDescription
    >;

    return Object.entries(fields).reduce(
      (newObj, [key, schemaDescription]) => {
        newObj[key as keyof T] = !schemaDescription.optional;
        return newObj;
      },
      {} as Record<keyof T, boolean>,
    );
  };

  const requiredFields = getRequiredFields();

  const isFieldRequired = (field: keyof T): boolean => {
    return requiredFields[field];
  };

  return {
    isFieldRequired,
  };
};

用途:

  const { isFieldRequired } = useIsFieldRequired<FormValues>(schema);

  return (
    <input name="input-name" required={isFieldRequired('input-name'} />
  )

© www.soinside.com 2019 - 2024. All rights reserved.