Custom React Hook to manage field validation
npm install react-field-validation-form> Custom React Hook for managing field and form level validation using Yup with support for nested data, arrays and async values.
 
``bash`
npm install --save react-field-validation-form
#### Basic
`jsx
import React, { useState } from 'react'
import { string } from 'yup'
import useFieldValidationForm from 'react-field-validation-form'
import { Button, Box, FormLabel, Input } from '@chakra-ui/core'
function Basic() {
const [values, setValues] = useState(null)
const {
formData,
errors: formErrors,
handleChange,
handleSubmit,
handleValidateField
} = useFieldValidationForm({
initialValues: {
email: '',
password: ''
},
validationSchema: {
email: string().required('Field Required!').email('Format invalid!'),
password: string()
.required('Field Required!')
.min(3, 'Minimum of 3 characters')
},
callBack: (outputValues) => {
setValues(outputValues)
}
})
return (
type='password'
name='password'
id='password'
value={formData.password}
onChange={handleChange}
onInput={handleValidateField}
/>
)
}
export default Basic
`
#### Nested Object
`jsx
import React, { useState } from 'react'
import { string } from 'yup'
import useFieldValidationForm from 'react-field-validation-form'
import { Button, Box, FormLabel, Input } from '@chakra-ui/core'
function Nested() {
const [values, setValues] = useState(null)
const {
formData,
errors: formErrors,
handleChange,
handleSubmit,
handleValidateField
} = useFieldValidationForm({
initialValues: {
user: {
name: '',
email: ''
}
},
validationSchema: {
user: {
name: string()
.required('Field Required!')
.min(3, 'Minimum of 3 characters'),
email: string().required('Field Required!').email('Format invalid!')
}
},
callBack: (outputValues) => {
setValues(outputValues)
}
})
return (
type='text'
name='user.email'
id='email'
value={formData.user.email}
onChange={handleChange}
onInput={handleValidateField}
/>
)
}
export default Nested
`
#### With Array
`jsx
import React, { useState } from 'react'
import { string } from 'yup'
import useFieldValidationForm from 'react-field-validation-form'
import {
Button,
Box,
FormLabel,
Input,
IconButton,
Flex
} from '@chakra-ui/core'
import { generate } from 'shortid'
function WithArray() {
const [values, setValues] = useState(null)
const {
formData,
errors: formErrors,
handleChange,
handleSubmit,
handleValidateField,
handleArrayOnChange,
handleValidateArrayField,
handleArrayRemoveField,
handleArrayPushField
} = useFieldValidationForm({
initialValues: {
name: '',
food: [{ id: '1', name: '' }]
},
validationSchema: {
name: string()
.required('Field Required!')
.min(3, 'Minimum of 3 characters'),
food: string()
.required('Field Required!')
.min(2, 'Minimum of 2 characters')
},
callBack: (outputValues) => {
const food = outputValues.food.reduce(
(acc, { id, name }) => [...acc, name],
[]
)
setValues({ ...outputValues, food })
}
})
return (
{formData.food.map((foodType, index) => (
Preferred food No: {index + 1}
type='text'
name='food'
id={foodType.id}
value={foodType.name}
onChange={(e) =>
handleArrayOnChange({ e, id: foodType.id, index })
}
onInput={(e) =>
handleValidateArrayField({ e, id: foodType.id })
}
/>
{formData.food.length > 1 && (
icon='close'
onClick={() =>
handleArrayRemoveField({ key: 'food', id: foodType.id })
}
marginLeft='2'
/>
)}
))}
onClick={() =>
handleArrayPushField({
key: 'food',
data: { id: generate(), name: '' }
})
}
>
Add new type of Food
)
}
export default WithArray
`
#### With Async Data
`jsx
import React, { useState, useEffect } from 'react'
import { string } from 'yup'
import useFieldValidationForm from 'react-field-validation-form'
import {
Button,
Box,
FormLabel,
Input,
IconButton,
Flex
} from '@chakra-ui/core'
import { generate } from 'shortid'
function Async() {
const [asyncData, setAsyncData] = useState(null)
const [isLoading, setLoading] = useState(false)
const [values, setValues] = useState(null)
const {
formData,
errors: formErrors,
handleChange,
handleSubmit,
handleValidateField,
handleArrayOnChange,
handleValidateArrayField,
handleArrayRemoveField,
handleArrayPushField
} = useFieldValidationForm({
initialValues: {
name: asyncData?.name ?? '',
food: asyncData?.food.length
? asyncData.food.map((type, index) => ({
id: ${index + 1},
name: type
}))
: [{ id: '1', name: '' }]
},
validationSchema: {
name: string()
.required('Field Required!')
.min(3, 'Minimum of 3 characters'),
food: string()
.required('Field Required!')
.min(2, 'Minimum of 2 characters')
},
callBack: (outputValues) => {
const food = outputValues.food.reduce(
(acc, { id, name }) => [...acc, name],
[]
)
setValues({ ...outputValues, food })
}
})
useEffect(() => {
if (!asyncData) {
setLoading(true)
setTimeout(() => {
setAsyncData({
name: 'Example Name',
food: ['fries', 'fish', 'eggs', 'tofu']
})
setLoading(false)
}, 3000)
}
}, [asyncData])
return (
{isLoading ? (
) : (
{formData.food.map((foodType, index) => (
Preferred food No: {index + 1}
type='text'
name='food'
id={foodType.id}
value={foodType.name}
onChange={(e) =>
handleArrayOnChange({ e, id: foodType.id, index })
}
onInput={(e) =>
handleValidateArrayField({ e, id: foodType.id })
}
/>
{formData.food.length > 1 && (
icon='close'
onClick={() =>
handleArrayRemoveField({
key: 'food',
id: foodType.id
})
}
marginLeft='2'
/>
)}
))}
onClick={() =>
handleArrayPushField({
key: 'food',
data: { id: generate(), name: '' }
})
}
>
Add new type of Food
Output Values to be sent back to server:{' '}
{values && JSON.stringify(values, null, 2)}
)}
)
}
export default Async
``
#### Check examples folder for in depth usage.
#### Or See them in action
MIT © VictorBaba