'How to use yup validation on dynamic form using react-hook-form with useFieldArray
I'm trying to create a dynamic form using react-hook-form's useFieldArray
hook. The user should be able to add or remove fields, thus making it dynamic. I've looked at this tutorial for inspiration, but the missing piece is how to implement error validation to the state, which will be an array of objects: {email: string}[]
. (The object will take more key/value pairs. I've left out the rest for simplicity.)
I've tried using yup
as validation schema. It looks like this:
const schema = yup.array().of(
yup.object().shape({
email: yup.string().email().required(),
}),
)
The implementation into react-hook-form is:
import * as yup from 'yup'
import { yupResolver } from '@hookform/resolvers/yup'
import { useForm, useFieldArray, Controller } from 'react-hook-form'
const { register, control, handleSubmit, errors } = useForm({
resolver: yupResolver(schema),
mode: 'onChange',
})
const { fields, append, remove } = useFieldArray({
control,
name: 'users',
})
The form is more or less according to the tutorial in the link above.
When console logging the error
object from useForm
hook it is consistently giving an empty object {}
. It doesn't seem like it works. I am probably missing something here. The question is what?
Solution 1:[1]
React Hook Form v7
yup with dynamic fields react hook form - useFieldArray
import { string, object, array } from 'yup';
const formSchema = {
name: string().required("Name is required").min(7, 'Message'),
};
const schema = object({
test: array()
.of(object().shape(formSchema))
});
export default schema;
const methods = useForm({
resolver: yupResolver(schema),
});
show the error
<div style={{ fontSize: 14 }}>{errors?.test?.[index]?.name?.message}</div>
Solution 2:[2]
perhaps you want to use the context
argument to switch your schema?
Context: This context object is mutable and will be injected into resolver's second argument or Yup validation's context object.
import * as React from "react";
import { useForm } from "react-hook-form";
import * as Joi from "joi";
const validationSchema1 = Joi.object({
username: Joi.string()
.alphanum()
.min(3)
.max(30)
.required()
});
const validationSchema2 = Joi.object({
username: Joi.string()
.alphanum()
.min(3)
.max(30)
.required()
});
const App = () => {
const [schemaContext, setSchemaContext] = useState({ schemaA: false })
const { register, handleSubmit, errors } = useForm({
context: schemaContext, // use the context switch here
resolver: async (data, context) => {
const { error, value: values } = context.is1 ? validationSchema1.validate(data, {
abortEarly: false
}) : validationSchema2.validate(data, {
abortEarly: false
});
return {
values: error ? {} : values,
errors: error
? error.details.reduce((previous, currentError) => {
return {
...previous,
[currentError.path[0]]: currentError
};
}, {})
: {}
};
}
});
const onSubmit = data => {
console.log(data)
};
return (
<div className="App">
<h1>resolver</h1>
<form onSubmit={handleSubmit(onSubmit)}>
<label>Username</label>
<input type="text" name="username" ref={register} />
{errors.username && <p>errors.username.message</p>}
<input type="submit" />
</form>
</div>
);
};
Solution 3:[3]
I think you should specify your array name. like this:
{
teammates: yupArray().of(
yupObject().shape({
email: stringSchemaBuilder("Email").email(),
expertise: arraySchemaBuilder(false, "Expertise", true, 2, 5),
})
),
};
where teammates is my array name
Solution 4:[4]
I used the useForm
hook's resolver property method to identify the validation scheme I should use from the value of a field in my form.
The code below worked for my use case maybe it can help you
function formValidatorSchemaByPaymentModalityType(paymentModalityType?: ModalityTypes) {
switch (paymentModalityType) {
case ModalityTypes.CREDIT_CARD:
return creditCardSchemaValidation;
default:
return defaultSchemaValidation;
}
}
const methods = useForm({
resolver: (data, context, options) => {
const validatorSchema = formValidatorSchemaByPaymentModalityType(
data.paymentType.value,
)
return yupResolver(validatorSchema)(data, context, options);
},
});
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Felipe Corredor |
Solution 2 | Bill |
Solution 3 | Haris Raharjo |
Solution 4 | Marcos Santos Dev |