DEV Community

rcblake
rcblake

Posted on

Fantastic Forms with React Hook Forms

With forms being a focal point of many applications, the ability to move swiftly in implementation is crucial as well as reusability and modular components. React Hook forms is here to cover those bases and more in the advancement in the space.

I'll start with why it's different and I'll give you a few stats as reference then I'll show you off some of the key basic features. I'll be using Formik as the leading comparison.

Like Formik, React Hook Form is a form builder library that aims to reduce the pain of creating forms with React. A big difference between the two is that React Hook Form is designed to make use of uncontrolled components to avoid unnecessary re-rendering caused by user inputs.

This makes for significantly less re-renders on the form as you aren't rendering on every keystroke. React Hook Form isolates input components from the rest, preventing the whole form to re-render for a single field change.

Other libraries, including Formik, rely on form updates to cascade changes to the inputs, and although it has some advantages in terms of flexibility, this has a huge cost on performance

Installation

npm install react-hook-form
Enter fullscreen mode Exit fullscreen mode

API References

The useForm API: this is one of those functions which you will be calling first before you apply any handling logic to your existing forms. It takes some optional arguments like mode, defaultValues, shouldFocusError, etc.

const { register } = useForm({
  mode: 'onSubmit',
  reValidateMode: 'onChange',
  defaultValues: {},
  resolver: undefined,
  context: undefined,
  shouldFocusError: true,
  shouldUnregister: true,
})
Enter fullscreen mode Exit fullscreen mode

As for its methods, take a look at how these are used:

register: allows you to register an input/select ref and apply validation rules into React Hook Form based on both HTML default and custom validations.

`<input name="test" ref={register} />

<input
  name="test"
  ref={
    register({
      required: true
    })
  }
/>
Enter fullscreen mode Exit fullscreen mode

errors: it’s an object which contains form errors and error messages corresponding to each field.

const { errors } = useForm();

<input name="singleErrorInput" ref={register({ required: true })} />
{errors.singleErrorInput && "Your input is required"}
Enter fullscreen mode Exit fullscreen mode

handleSubmit: it’s a function that will pass the form data when form validation is successful and can be invoked remotely as well.

const { register, handleSubmit } = useForm();
const onSubmit = (data, e) => console.log(data, e);
const onError = (errors, e) => console.log(errors, e);

<form onSubmit={handleSubmit(onSubmit, onError)}>
      <input name="firstName" ref={register} />
      <input name="lastName" ref={register} />
      <button type="submit">Submit</button>
 </form>
Enter fullscreen mode Exit fullscreen mode

setError: allows you to manually set one or more errors.

const { setError, errors } = useForm();

<input 
  name="username"
  type="text"
  onChange={() => {
      setError("username", {
      type: "manual",
      message: "Dont Forget Your Username Should Be Cool!"
    });
  }}
  ref={register} />

  {errors.username && <p>{errors.username.message}</p>}
Enter fullscreen mode Exit fullscreen mode

The Controller API: it’s a wrapper component that makes it easier to work with external components from other libraries and frameworks, specifically helpful Material UI.

<Controller
  control={control}
  name="test"
  render={(
    { onChange, onBlur, value, name, ref },
    { invalid, isTouched, isDirty }
  ) => (
    <Checkbox
      onBlur={onBlur}
      onChange={(e) => onChange(e.target.checked)}
      checked={value}
      inputRef={ref}
    />
  )}
/>
Enter fullscreen mode Exit fullscreen mode

Validation: RHF in-line validation is quick and simple allowing for validation on data type, length, or even regex patterns

<input name="firstName" 
  ref={register({ required: true, maxLength: 20 })} />
<input name="lastName" 
  ref={register({ pattern: /^[A-Za-z]+$/i })} />
<input name="age" type="number" 
  ref={register({ min: 18, max: 99 })} />
Enter fullscreen mode Exit fullscreen mode

Combining this simplicity into what can become very complication with MUI or any other design library, you can just insert the ref above into the TextField component of the library and you've got your instant front end validation with limited rendering and 0 dependencies.

And if you're used to using schema validation like Yup, its even easier to implement.

Toss is multi-error options (per field) and you've got amazing user forward forms.

Top comments (0)