I'm using react-hook-form with the latest version of yup, and I'm trying to implement dynamic validation that depends on a type field selected by the user. The validation schema is generated using yup.lazy, and it returns different rules based on the current value of type.
Here’s how I'm initializing the form:
const defaultValues = getDefaultValues(type, dataToEdit);
const schema = getSchema(t);
const methods = useForm<any>({
reValidateMode: 'onChange',
resolver: yupResolver(schema),
defaultValues,
context: { rawMaterials, defaultValues },
});
Here’s a simplified version of my getSchema function:
const getSchema = (t) =>
yup.lazy((value, context) => {
console.log('Type called with context:', context);
console.log('Schema called with:', value);
return yup.object().shape({
purchaseOrderTasks: yup.array().of(
yup.object().shape({
cigar: yup.string().when([], {
is: () => value.type === PURCHASE_ORDER_TYPES.CIGAR,
then: (schema) => schema.required(t('validation.required')),
otherwise: (schema) => schema.nullable(),
}),
tobacco: yup.string().when([], {
is: () => value.type === PURCHASE_ORDER_TYPES.TOBACCO,
then: (schema) => schema.required(t('validation.required')),
otherwise: (schema) => schema.nullable(),
}),
// ... more fields
})
),
});
});
What I'm trying to achieve When the user changes the value of the type field inside the form, the Yup validation should update immediately to reflect the new rules (e.g., require cigar if type === CIGAR, or tobacco if type === TOBACCO, etc).
The issue
type never changes
The schema is created once during useForm initialization.
When the user changes type, the form shows the correct fields, but the validation schema does not update accordingly.
Since yup.lazy depends on value.type, it seems like value passed to the resolver is stale or not updated.
I want to:
Keep react-hook-form and yup
Dynamically adjust validation logic based on form values (especially type)
Any best practices or patterns for this?
It is my mistake; I added tested code for validation/test before any updated. Value params in lazy are correctly updated.