Skip to content

Get Started

Simple form validation with React Hook Form.

Installation

Installing React Hook Form only takes a single command and you're ready to roll.

npm install react-hook-form

Example

The following code will demonstrate the basic usage:

CodeSandbox
import React from 'react'
import useForm from 'react-hook-form'

export default function App() {
  const { register, handleSubmit, watch, errors } = useForm()
  const onSubmit = data => { console.log(data) }

  console.log(watch('example')) // watch input value by passing the name of it

  return (
    {/* "handleSubmit" will validate your inputs before invoking "onSubmit" */}
    <form onSubmit={handleSubmit(onSubmit)}>
    {/* register your input into the hook by invoking the "register" function */}
      <input name="example" defaultValue="test" ref={register} />
      
      {/* include validation with required or other standard HTML validation rules */}
      <input name="exampleRequired" ref={register({ required: true })} />
      {/* errors will return when field validation fails  */}
      {errors.exampleRequired && <span>This field is required</span>}
      
      <input type="submit" />
    </form>
  )
}

Video Tutorial

In this video tutorial, I have demonstrated the basic usage and concept of using React Hook Form.

Register fields

One of the key concepts for React Hook Form is to register your uncontrolled component into the Hook and hence enabling its value to be validated and gathered for submitting.

Note: Each field is required to have a unique name as a key for the registration process.

Note: React Native will need to use a manual register command (e.g.: register({ name: 'test' }, { required: true })

import React from 'react'
import useForm from 'react-hook-form'

export default function App() {
  const { register, handleSubmit } = useForm()
  const onSubmit = data => console.log(data)
   
  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      <input name="firstName" ref={register} />
      <select name="gender" ref={register}>
        <option value="male">male</option>
        <option value="female">female</option>
      </select>
      <input type="submit" />
    </form>
  );
}

Apply validation

React Hook Form make form validation easy by aligning with existing HTML standard form validation.

List of validation rules supported by:

  • required
  • min
  • max
  • minLength
  • maxLength
  • pattern
  • validate

You can read more detail on each rule at the register section.

import React from 'react'
import useForm from 'react-hook-form'

export default function App() {
  const { register, handleSubmit } = useForm()
  const onSubmit = data => console.log(data)
   
  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      <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 })} />
      <input type="submit" />
    </form>
  );
}

Adapting existing form

Working on an existing form is simple. The important step is to apply register into existing component's ref.
import React from 'react'
import useForm from 'react-hook-form'

// The following component is an example of your existing Input Component 
const Input = ({ label, register, required }) => ( 
  <>
    <label>{label}</label>
    <input name={label} ref={register({ required })} />
  </>
)

// you can use React.forwardRef to pass the ref too
const Select = React.forwardRef(({ label, register }, ref) => ( 
  <>
    <label>{label}</label>
    <select name={label} ref={ref}>
      <option value="20">20</option>
      <option value="30">30</option>
    </select>
  </>
))

export default function App() {
  const { register, handleSubmit } = useForm()
  const onSubmit = data => console.log(data)
   
  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      <Input label="First Name" register={register} required />
      <Select label="Age" ref={register} />
      <input type="submit" />
    </form>
  )
}

Work with UI library

React Hook Form has made it easy to integrate with external UI component libraries.

Note: Most UI libraries do expose innerRef or ref to register. However, if that's not the case. For example react-select or react-datepicker, you can use register at useEffect and update the value via setValue.

CodeSandbox
import React from 'react';
import useForm from 'react-hook-form';
import Select from "react-select";
import Input from "@material-ui/core/Input";
import { Input as InputField } from 'antd';

export default function App() {
  const { register, handleSubmit, setValue } = useForm();
  const onSubmit = data => console.log(data);
  const [values, setReactSelectValue] = useState({ selectedOption: [] });

  const handleMultiChange = selectedOption => {
    setValue("reactSelect", selectedOption);
    setReactSelectValue({ selectedOption });
  }
  
  const handleChange = (e) => {
    setValue("AntdInput", e.target.value);
  }
  
  React.useEffect(() => {
    register({ name: "reactSelect" }); // custom register react-select 
    register({ name: "AntdInput" }); // custom register antd input
  }, [register])

  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      <Input name="HelloWorld" inputRef={register} />
      <InputField name="AntdInput" onChange={handleChange} />
      <Select
        value={values.selectedOption}
        options={options}
        onChange={handleMultiChange}
        isMulti
      />
      <input type="submit" />
    </form>
  );
}

Integrate global state

React Hook Form doesn't require you to have a state management to store your data, but you can easily integrate with one.
import React from 'react'
import useForm from 'react-hook-form'
import { connect } from 'react-redux'
import updateAction from './actions'

export default function App(props) {
  const { register, handleSubmit, setValue } = useForm()
  // Submit your data into Redux store
  const onSubmit = (data) => props.updateAction(data)
  
  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      <Input name="firstName" defaultValue={props.firstName} ref={register} />
      <Input name="lastName" defaultValue={props.lastName} ref={register} />
      <input type="submit" />
    </form>
  );
}

// Connect your component with redux
connect(({ firstName, lastName }) => ({ firstName, lastName }), updateAction)(YourForm)

Handle errors

React Hook Form provides an errors object to show you the errors within the form.
import React from 'react'
import useForm from 'react-hook-form'

export default function App() {
  const { register, errors } = useForm()
  
  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      <Input name="firstName" ref={register({ required: true })} />
      {errors.firstName && 'First name is required'}
      <Input name="lastName" ref={register({ required: true })} />
      {errors.lastName && 'Last name is required'}
      <input type="submit" />
    </form>
  );
}

Want to learn more?

Check out the React Hook Form documentation and learn all about the API.