React Hook useForm

useForm provides an interface around an object for use in forms.

Install

npm install --save react-hook-use-form

Usage

The best useForm experiance comes when using Typescript.

Lets say you want to collect a users name and email for a newsletter form.

const NewsletterSignUp: React.FunctionComponent = () => {
  const {formBind, bind, onSubmit} = useForm({
    name: '',
    email: ''
  })

  onSubmit((data) => {
    // `data` is the forms state when it was submitted
    doSignup(data.name, data.email)
  })

  return <form {...formBind()}>
    <input {...bind('name')} />
    <input {...bind('email')} />
    <input type="submit" value="Sign Up!" />
  </Form>
}

useForms output is an object with this structure:

property type value
bind (field: keyof T) => {value, onChange, name} Used to bind to a single field.
clear () => void Function that sets the form back to its initial value.
controlledInput (fieldName: keyof T) => ControlledInput Function that is used to create input fields (See Creating your own input).
data T The current state of the form.
formBind () => {onSumbit} Used to bind a forms submit action to useForm
onSubmit (handler: (data: T) => void) => void A function which takes a callback to be used when the form is submitted.
validate (field: keyof T, validator: (value: any) => boolean) => void A function that takes the field name and validation function as arguments.
valid (field?: keyof T) => boolean A function that checks the validity of one field or the whole form and returns a boolean value.
set (data: T) => void Function to set the data to a given value. Useful if you want to use one form to edit multiple entries.
label `(field: keyof T) => {for} Returns the fields label for.
changed (field?: keyof T) => boolean Has the given field, or any field changed from the intial data.

Validation

Validating fields with useForm is easy. Going back to the earlier example, lets ensure that the email contains an @

const NewsletterSignUp: React.FunctionComponent = () => {
  const {valid, bind, formBind, validate} = useForm({
    name: '',
    email: ''
  })

  validate('email', (value) => {
    return value.indexOf('@') > -1
  })

  return <form {...formBind()}>
    <input {...bind('name')} style={{color: valid('name') ? '#000' : '#f00'}} />
    <input {...bind('email')} style={{color: valid('email') ? '#000' : '#f00'}} />
    <input type="submit" value="Subscribe" disabled={!valid()} />
  </form>
}

Creating your own input

Sometimes simply using bind wont work as your not using and input and you want to have a custom input.

useForm returns a function of controlledInput which gives more control over a single field.

controlledInput returns the following:

property type value
field keyof T The current field
value T[field] The current value (connected to state)
update (newValue: T[field]) => void Change the value to the supplied value
valid () => boolean Returns a boolean value for the fields current validity
bind {value, onChange, name} The same as if you had called bind(field) directly from useForm
id string The id of the input.