简体   繁体   English

在触摸字段之前运行 Formik Yup 验证

[英]Formik Yup validation running before field is touched

I have a form that has a field items , which stores an array of objects with the properties image and name .我有一个表单,它有一个字段items ,它存储了一个带有属性imagename的对象数组。 The image property accepts a file but is optional, the name field is required. image属性接受一个文件,但它是可选的, name字段是必需的。

For some reason, when I touch the name field, the image field validation kicks in and it throws the error "Image is too large", which can be seen from formik's errors object.出于某种原因,当我触摸名称字段时,图像字段验证开始并抛出错误“图像太大”,这可以从 formik 的错误对象中看出。 I don't understand why this is happening.我不明白为什么会这样。 Below is the code for the component and a codesandbox which you can view here https://codesandbox.io/s/new-fog-xs2wb?file=/src/components/form.js下面是组件的代码和一个代码和框,你可以在这里查看https://codesandbox.io/s/new-fog-xs2wb?file=/src/components/form.js

import React from 'react';
import { Formik, Field, FieldArray } from 'formik';
import * as Yup from 'yup';

function MyForm(props) {
  const FILE_SIZE = 5 * 1024 * 1024;
  const SUPPORTED_FORMATS = ["image/jpg", "image/jpeg", "image/gif", "image/png"];

  const validationSchema = Yup.object().shape({
    items: Yup.array().of(Yup.object().shape({
      image: Yup.mixed()
          .test("fileSize", "Image is too large", (value) => value && value.size <= FILE_SIZE)
          .test(
            "fileFormat",
            "Unsupported Format - We only allow images.",
            (value) => value && SUPPORTED_FORMATS.includes(value.type)
          ),
       name: Yup.string().required('Required') 
    }))
  });

  const initialValues = { items: [{
    image: undefined,
    name: ''
  }]}

  return (
    <div className="container">
      <Formik enableReinitialize={true}
              initialValues={initialValues}
              validationSchema={validationSchema}
              onSubmit={async (values, { setSubmitting, resetForm }) => {
                setSubmitting(true);
                console.log(values);
                setSubmitting(false);
              }}>
              {({
                values,
                errors,
                touched,
                handleChange,
                handleBlur,
                handleSubmit,
                isSubmitting,
                setFieldValue,
              }) => (
                <form className="mt-3" onSubmit={handleSubmit}>
                    <FieldArray name="items">
                    {({ push, remove }) => (
                      <React.Fragment>
                      {values.items && values.items.length && values.items.map((item, index) => (
                        <div key={index}>
                          {/* <Field name={`items[${index}].image`} /> */}
                          <div className="form-group">
                              <label htmlFor="name">Name</label>
                              <input name={`items[${index}].name`} className="form-control" id="name" aria-describedby="nameHelp" onChange={handleChange} onBlur={handleBlur} />
                              <small id="nameHelp" className="form-text text-muted">Enter a descriptive name for the item.</small>
                          </div>
                          <button type="button" className="btn btn-danger mr-2 mb-2" onClick={() => remove(index)}>Remove</button>
                        </div>
                      ))}
                      <button type="button" className="btn btn-secondary mr-2 mt-4" onClick={() => push({image: undefined, name: ''})}>Add</button>
                      <button type="submit" disabled={isSubmitting} className="btn btn-primary mt-4">Submit</button>
                      <pre className="mt-2">{JSON.stringify(errors, null, 2)}</pre>
                      </React.Fragment>
                    )}
                    </FieldArray>
                </form>
              )}
      </Formik>
    </div>)
}

export default MyForm;

How do I get this to work as desired?我如何让它按预期工作? Your help is greatly appreciated.非常感谢您的帮助。

The function that you used inside the test method should return false to show the resp error msg .您在测试方法中使用的函数应返回 false 以显示响应错误 msg Ref: https://github.com/jquense/yup#mixedtestoptions-object-schema参考: https : //github.com/jquense/yup#mixedtestoptions-object-schema

So you should do !(value?.size > FILE_SIZE) and所以你应该做!(value?.size > FILE_SIZE)
!(value && !SUPPORTED_FORMATS.includes(value.type)) to make it work! !(value && !SUPPORTED_FORMATS.includes(value.type))使其工作!

Code updates:代码更新:

image: Yup.mixed()
          .test(
             "fileSize", 
             "Image is too large",
             (value) => !(value?.size > FILE_SIZE)
          )
          .test(
            "fileFormat",
            "Unsupported Format - We only allow images.",
            (value) => !(value && !SUPPORTED_FORMATS.includes(value.type))
          ),

Formik provides many utilities for validation, you can use below combo for your purpose: Formik提供了许多用于验证的实用程序,您可以根据需要使用以下组合:

 validateOnChange={false} validateOnBlur={true}

This will fix your problem, if any case it will not work then remove validateOnBlur这将解决您的问题,如果在任何情况下都不起作用,则删除validateOnBlur

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM