Getting Started Form

{
  "name": "John"
}
{}

TIP: Open react developer tools, go to preferences and enable Highlight updates and then start typing on the form inputs to see which components update.

Code

import React, { useRef } from 'react'

import { useFieldState, useForm, useFormState } from 'react-form-hooks'

/**
 This is an example where everything is defined in a single component.
 This may be fine for getting started. But it can become cumbersome to manage
 especially when working with large number of inputs.
 Also, when using hooks, the component hosting the hook will be re-rendered
 whenever the state is updated like the field and form state here.
 For large forms, the form would perform better if the hooks are moved to their
 own components and then reused.

 Check the BasicExample example for a sample pattern to reuse code.
 */
function MyForm() {
  // useRef is necessary here because otherwise, the form will be reset
  // when initialValues reference changes on re-render.
  const initialValues = useRef({ name: 'John' }).current
  const form = useForm({ initialValues })

  const formState = useFormState(form)
  const { anyError, anyDirty, anyTouched, values, errors } = formState

  const nameState = useFieldState(form, 'name')
  const ageState = useFieldState(form, 'age', undefined, {
    validate: value => value < 18 && 'age should be above 18',
  })
  const emailState = useFieldState(form, 'email', undefined, {
    validate: v => !/^\S+@\S+\.\S+$/.test(v) && 'should be a valid email',
  })

  const onSubmit = values => alert(JSON.stringify(values, null, 2))

  return (
    <form onSubmit={form.formActions.submitHandler(onSubmit)}>
      <div>
        <label htmlFor="name">Name</label>
        <input
          id="name"
          onChange={e =>
            form.fieldActions.changeFieldValue(
              'name',
              e.target.value.toUpperCase()
            )
          }
          onBlur={() => form.fieldActions.touchField('name')}
          value={nameState.value}
        />
      </div>
      <div>
        <label htmlFor="age">Age</label>
        <input
          id="age"
          type="number"
          onChange={e =>
            form.fieldActions.changeFieldValue(
              'age',
              e.target.value.toUpperCase()
            )
          }
          onBlur={() => form.fieldActions.touchField('age')}
          value={ageState.value}
        />
      </div>
      <div>
        <label htmlFor="email">Email</label>
        <input
          id="email"
          onChange={e =>
            form.fieldActions.changeFieldValue('email', e.target.value)
          }
          onBlur={() => form.fieldActions.touchField('email')}
          value={emailState.value}
        />
      </div>

      <pre>{JSON.stringify(values, null, 2)}</pre>
      <pre>{JSON.stringify(errors, null, 2)}</pre>

      {anyError && <div>Form Error</div>}
      {anyDirty && <div>Form Dirty</div>}
      {anyTouched && <div>Form Touched</div>}
      <button type="submit">Submit</button>
      <button onClick={() => form.formActions.resetFormValues()}>Reset</button>
    </form>
  )
}

export default MyForm