Use with React Hook Form
💡️
React Hook Form (opens in a new tab) is a popular package developers use to validate forms. Koval UI input and form API is compatible with this package.
Validate field
Example of a single field validation.
import {useForm} from 'react-hook-form'; import {Form as KovalForm, InputText, Button, FormField} from 'koval-ui'; // Handle form successful submit const onSubmit = (data) => console.log(data); export default () => { /** * React hook form basic setup. Click Submit to validate. * @see https://react-hook-form.com/docs/useform */ const { getFieldState, register, handleSubmit, formState: {errors}, } = useForm({ /** * Mode 'all' is recommended to use with Koval UI * @see https://react-hook-form.com/docs/useform#mode */ mode: 'all', }); /** * Get validation state from React Hook Form * @see https://react-hook-form.com/docs/useform/getfieldstate */ const {invalid, isTouched} = getFieldState('exampleHint'); // Convert React Hook Form validation state to Koval UI const validation = (() => { if (invalid) { // trigger an error for the input return 'error'; } else if (!isTouched) { // don't show successful validation, when input value is unchanged return 'pristine'; } // everything else considered to be successful validation return 'valid'; })(); return ( <KovalForm onSubmit={handleSubmit(onSubmit)}> <FormField required label="Error message demo" // Display hook form errors as hint message below input hint={errors.exampleHint?.message}> <InputText placeholder="More than 3 symbols" autoComplete="off" {...register('exampleHint', { required: 'This field is required!', minLength: {value: 3, message: 'Minimum 3 symbols'}, })} // Synchronize input validation state with React Hook Form validation={validation} // Set browser input error message errorMessage={errors.exampleHint?.message} /> </FormField> <div> <Button type="submit">Submit</Button> </div> </KovalForm> ); };
Validate state with schema
React hook form is capable of doing complex schema-based validations. Here is an example using yup (opens in a new tab).
import {useCallback} from 'react'; import {Form as KovalForm, InputText, Button, FormField, InputNumber} from 'koval-ui'; import {useForm} from 'react-hook-form'; import {yupResolver} from '@hookform/resolvers/yup'; import * as yup from 'yup'; /** * Form validation schema * @see https://github.com/jquense/yup?tab=readme-ov-file#schema-basics */ const schema = yup .object({ firstName: yup.string().required('Required field!').min(3, 'Minimum 3 symbols'), age: yup .number() .transform((value, originalValue) => { // Remove commas and convert to number return originalValue === '' ? null : value; }) .required('Required field!') .moreThan(99, 'More than 99') .typeError('Age must be a number'), }) .required(); // Handle form successful submit const onSubmit = (data) => console.log(data); /** * Utility function to determine the ValidationState of a form field based on its invalid and isTouched properties */ const getValidation = ({ invalid, isTouched, }) => { if (invalid) { // trigger an error for the input return 'error'; } else if (!isTouched) { // don't show successful validation, when input value is unchanged return 'pristine'; } // everything else considered to be successful validation return 'valid'; }; export default () => { /** * React hook form basic setup * @see https://react-hook-form.com/docs/useform */ const {register, handleSubmit, formState, getFieldState, reset} = useForm({ // Set schema validation with yup resolver: yupResolver(schema), defaultValues: { firstName: undefined, age: undefined, }, mode: 'all', }); const firstNameValidity = getValidation(getFieldState('firstName')); const ageValidity = getValidation(getFieldState('age')); const handleReset = useCallback(() => { // Handle form reset with RHF reset(); }, [reset]); return ( <KovalForm onSubmit={handleSubmit(onSubmit)}> <FormField label="First name" // Set conditional hint from React Hook Form state hint={formState.errors.firstName?.message}> <InputText {...register('firstName')} // Synchronize input validation state with React Hook Form validation={firstNameValidity} // Set browser input error message errorMessage={formState.errors.firstName?.message} /> </FormField> <FormField label="Age" hint={formState.errors.age?.message}> <InputNumber {...register('age')} validation={ageValidity} errorMessage={formState.errors.age?.message} /> </FormField> <div> <Button type="submit">Submit</Button> <Button type="button" variant="alternative" onClick={handleReset}> Reset </Button> </div> </KovalForm> ); };