为什么自定义输入验证和 setError() 在使用 useField() 时不起作用?

Why custom input validation and setError() won't work when using useField()?

我在表格中创建了我面临的问题的最小版本。我想让某些 InputFields 具有最大和最小范围。如果用户键入超出该范围的内容,我将使用 setError() 设置错误字段。但是,验证并不总是有效。例如,如果我在 CGPA 字段中键入 555,我会看到错误,但如果我键入 55 则看不到错误,而我已将范围指定为 0 到 4。

代码沙箱here

您可以为此创建自己的自定义验证函数,这是一个示例

福米克场:

<Field
    type="number"
    name="myNumber"
    placeholder="Please input something"
    validate={(event) => Validators.customFieldLevelValidation(event, [Validators.required, Validators.minLength(6), Validators.maxLength(12)])} />

自定义验证器Class:

class Validators {
    static customFieldLevelValidation = (value, validations) => {
        for (let validation of validations) {
            const result = validation(value);
            if (result) {
                return result;
            }
        }
        return null;
    };

    static maxLength = max => value =>
        value && value.length > max ? `Must be ${max} characters or less` : undefined;

    static minLength = min => value =>
        value && value.length < min ? `Must be ${min} characters or more` : undefined;
}

按照this and this,我想出了解决办法。诀窍是将一个对象传递给 useField() 而不是像我所做的那样只传递道具。

所以,InputField.tsx 应该是这样的:


function InputField({ color, ...props }: TInputFieldProps) {
  const [field, { error }] = useField({
    name: props.name,
    validate: (value) => {
      let message: string = undefined;
      if (props.type === "number" && (props.min || props.max)) {
        if (parseFloat(value) > parseFloat(props.max as string)) {
          message = `The value of ${props.label} cannot be more than ${props.max}`;
        }

        if (parseFloat(value) < parseFloat(props.min as string)) {
          message = `The value of ${props.label} cannot be less than ${props.min}`;
        }
      }
      return message;
    },
    type: props.type,
  });

  return (
    <FormControl
      error={!!error}
      style={{ marginTop: "10px", marginBottom: "20px" }}
    >
      <FormLabel htmlFor={props.name}>{props.label}</FormLabel>
      <Input
        {...props}
        {...field}
        id={field.name}
        inputProps={{
          min: props.min ?? props.min,
          max: props.max ?? props.max,
          step: props.step ?? props.step,
        }}
      />
      {error && <FormHelperText error={!!error}>{error}</FormHelperText>}
    </FormControl>
  );
}

export default InputField;

尽管如此,我仍然不确定为什么 setError() 会出现这样的问题。这可能与陈旧状态有关。

根据我的测试,如果您使用的是 Yup,这不会破坏 Yup 验证,这太棒了。我在这里不能依赖 Yup 的原因是因为 minmax 值来自解析我原来问题中的文件上传。