I have a form that has a field items
, which stores an array of objects with the properties image
and name
. The image
property accepts a file but is optional, the name
field is required.
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. 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
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.
value
in the test function defined? can you log it? My thinking would be that it is not defined when you click on different field, which causing the test function to return false and fail validation when the field is empty – szczocik