# Figuring out Yup dynamic validation schema - Fri 27th Nov, 2020
In order to create the dynamic form schema, I had to do 3 things:
1. Set the schema into state for later updating:
```typescript=
const [validationSchema, setValidationSchema] = useState<ObjectWithSchema>({
// ...
Message: yup.object().shape({
message: yup.string().trim().required(t('recognise:validationSchema.message.required')),
}),
DynamicForm: yup.object().shape({
// form is dynamic and schema will be updated later
details: yup.object().shape({}),
}),
})
```
(The key here is the name of the screen)
2. Create an empty Yup `object` in the base schema:
```typescript=
DynamicForm: yup.object().shape({
// form is dynamic and schema will be updated later
details: yup.object().shape({}),
}),
```
3. Use context to expose the schema to the subsequent screen
4. In the dynamic form screen, create and update the schema stored in state:
```typescript=
useEffect(() => {
// if field is not required, don't validate
const requiredElements = (nominationFormElements ?? []).filter((element) =>
element.validation.some(
(validationObj) => validationObj.name === 'required' && element.type !== 'sectionbreak'
)
)
// create dynamic schema of required form fields
const nominationFormSchema = requiredElements.reduce((acc, curr) => {
const requiredValidation = curr.validation.find((validationObj) => validationObj.name === 'required')
switch (curr.type) {
case 'checkbox':
return {
...acc,
[curr.id]: yup
.array()
.min(1, requiredValidation?.message ?? t('recognise:validationSchema.general.required')),
}
case 'file':
return acc
default:
return {
...acc,
[curr.id]: yup
.string()
.required(requiredValidation?.message ?? t('recognise:validationSchema.general.required')),
}
}
}, {})
// create nomination form inital values for Formik
const nominationFormInitialValues = requiredElements.reduce((acc, curr) => {
switch (curr.type) {
case 'checkbox':
return {
...acc,
[curr.id]: [],
}
case 'file':
return {
...acc,
[curr.id]: '',
}
default:
return {
...acc,
[curr.id]: '',
}
}
}, {})
// Set nomination form initial values into formik on mount, otherwise the validation won't work
setFieldValue('nominationDetails', nominationFormInitialValues)
// update validation schema state
setValidationSchema((prevValidationSchema) => ({
...prevValidationSchema,
NominationForm: yup.object().shape({ nominationDetails: yup.object().shape(nominationFormSchema) }),
}))
}, [nominationFormElements, setValidationSchema, t, setFieldValue])
```
The whole setup was quite difficult to figure out, but it's good to know how to handle dynamic forms with Formik and Yup.
###### tags: `programmingjournal` `2020` `C+` `nominations` `Formik` `yup` `validation` `dynamic`