Using react-hook-form
— react — 3 min read
React Hook Form is a library that helps you validate forms in React. It’s straightforward to use and performant by adopting the use of uncontrolled inputs using ref
.
To install React Hook Form, run the following command.
npm i react-hook-form
Use React Hooks in a form
- Import the
useForm
hook from the package register
the input field into React Hook Form so that it is available for the validation and for trackinghandleSubmit
will be connected to the form’sonSubmit
event to handle submission
import { useForm } from `react-hook-form`const { register, handleSubmit } = useForm()
const onFormSubmit = data => console.log(data)const onErrors = errors => console.error(errors)
<form onSubmit={handleSubmit(onFormSubmit, onErrors)} > <input type="text" name="firstName" {...register('firstName')} /></form>
Validate forms
required
indicates if the field is required or not. If this property is set totrue
, then the field cannot be emptyminlength
andmaxlength
set the minimum and maximum length for a string input valuemin
andmax
set the minimum and maximum values for a numerical valuetype
indicates the type of the input field; it can be email, number, text, or any other standard HTML input typespattern
defines a pattern for the input value using a regular expression
<input name="name" type="text" {...register('name', { required: true } )} />
Example
import React from "react";import { useForm } from "react-hook-form";
const RegisterForm = () => { const { register, handleSubmit, formState: { errors } } = useForm(); const handleRegistration = (data) => console.log(data); const handleError = (errors) => {};
const registerOptions = { name: { required: "Name is required" }, email: { required: "Email is required" }, password: { required: "Password is required", minLength: { value: 8, message: "Password must have at least 8 characters" } } };
return ( <form onSubmit={handleSubmit(handleRegistration, handleError)}> <div> <label>Name</label> <input name="name" type="text" {...register('name', registerOptions.name) }/> <small className="text-danger"> {errors?.name && errors.name.message} </small> </div> <div> <label>Email</label> <input type="email" name="email" {...register('email', registerOptions.email)} /> <small className="text-danger"> {errors?.email && errors.email.message} </small> </div> <div> <label>Password</label> <input type="password" name="password" {...register('password', registerOptions.password)} /> <small className="text-danger"> {errors?.password && errors.password.message} </small> </div> <button>Submit</button> </form> );};export default RegisterForm;
Integrating Controller Inputs.
This library embraces uncontrolled components and native HTML inputs. However, it's hard to avoid working with external controlled components and it provides a wrapper component, Controller, to streamline the integration process.
import { useForm, Controller, SubmitHandler } from "react-hook-form"import { TextField, Checkbox } from "@material-ui/core"
interface IFormInputs { TextField: string MyCheckbox: boolean}
function App() { const { handleSubmit, control, reset } = useForm<IFormInputs>({ defaultValues: { MyCheckbox: false, }, }) const onSubmit: SubmitHandler<IFormInputs> = (data) => console.log(data)
return ( <form onSubmit={handleSubmit(onSubmit)}> <Controller name="MyCheckbox" control={control} rules={{ required: true }} render={({ field }) => <Checkbox {...field} />} /> <input type="submit" /> </form> )}
You can use useController
hook instead of <Controller />
wrapper
import React from 'react';import { UseControllerProps, useController } from 'react-hook-form';import { Checkbox, withTheme } from '@group/theme';
interface ConfirmationBoxProps { label: string | React.ReactNode; isDisabled: boolean; isRequired: boolean;}
const Field = ({ name, control, label, isDisabled, isRequired,}: UseControllerProps & ConfirmationBoxProps) => { const { field } = useController({ name, control, rules: { required: isRequired, }, });
return ( <div className="form-input"> <Checkbox disabled={isDisabled} key={field.name} styleVariation="default" label={label} htmlName="confirmSafeguarding-box" value="confirmSafeguarding" className="confirmation-box" checked={field.value} {...field} /> </div> );};
export const ConfirmationBox = withTheme(Field);