Back to overview

React Hook Form

FormHooksReact

react-hook-from

// https://github.com/react-hook-form/react-hook-form
import React, {ChangeEvent} from 'react';
import {useForm} from 'react-hook-form';

function App() {
  const {
    register,
    handleSubmit,
    formState: {errors},
  } = useForm();
  const onSubmit = (data) => console.log(data);

  // use with jsx <input onChange={changeUpdate} />
  function changeUpdate(e: ChangeEvent<HtmlInputElement>) {
    setCount(+e.target.value);
  }

  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      <input {...register('firstName')} /> {/* register an input */}
      <input {...register('lastName', {required: true})} />
      {errors.lastName && <p>Last name is required.</p>}
      <input {...register('age', {pattern: /\d+/})} />
      {errors.age && <p>Please enter number for age.</p>}
      <input type="submit" />
    </form>
  );
}

Normal Form

Controlled Form

// For complex nested update: https: //github.com/immerjs/use-immer

import {useState, ChangeEvent} from 'react';

export default function ControlledForm() {
  const [person, setPerson] = useState({
    firstName: 'Derek',
    lastName: 'Wang',
    email: 'derekw@sculpture.com',
    isSoldier: false,
  });

  function handleChange(e: ChangeEvent<HTMLInputElement>) {
    const value = e.target.type === 'checkbox' ? e.target.checked : e.target.value;

    setPerson({
      ...person,
      [e.target.name]: value,
    });
  }

  function handleSubmit() {
    // use person state
  }

  return (
    <form onSubmit={handleSubmit}>
      <label>
        First name:
        <input name="firstName" type="text" value={person.firstName} onChange={handleChange} />
      </label>
      <label>
        Last name:
        <input name="lastName" type="text" value={person.lastName} onChange={handleChange} />
      </label>
      <label>
        Email:
        <input name="email" type="text" value={person.email} onChange={handleChange} />
      </label>
      <label>
        isSoldier:
        <input name="isSoldier" type="checkbox" value={person.isSoldier} onChange={handleChange} />
      </label>
      <p>
        {person.firstName} {person.lastName} ({person.email})
      </p>
      <button type="submit">Submit</button>
    </form>
  );
}

Uncontrolled Form

This is useful especially when the form controls are returned by a GET response. e.g. some checkboxes' values are not known at build time.

export function getFormData(e: React.FormEvent<HTMLFormElement>) {
  const formData: {[key: string]: any} = {};
  (Array.from((e.target as HTMLFormElement).elements) as HTMLFormElement[]).forEach((e) => {
    if (!e.name) {
      return;
    }

    // normal html input
    if (e.getAttribute('type') !== 'checkbox') {
      formData[e.name] = e.value;
      return;
    }

    // save checkbox checked values
    if (e.checked) {
      e.name in formData ? formData[e.name].push(e.value) : (formData[e.name] = [e.value]);
    }
  });

  return formData;
}
// For complex nested update: https: //github.com/immerjs/use-immer

import {FormEvent} from 'react';

export default function UncontrolledForm() {
  handleSubmit = (event: FormEvent<HTMLFormElement>) => {
    event.preventDefault();

    // way 1
    const firstName = event.target.firstName.value;
    const lastName = event.target.lastName.value;

    // way 2:
    const formData: any = {};
    (Array.from(event.currentTarget.elements) as HTMLFormElement[]).forEach((e) => {
      if (e.name) {
        formData[e.name] = e.value;
      }
    });

    // Here we do something with form data
    console.log(firstName, lastName);
  };

  return (
    <form onSubmit={handleSubmit}>
      <label>
        First name:
        <input name="firstName" type="text" />
      </label>
      <label>
        Last name:
        <input name="lastName" type="text" />
      </label>
      <label>
        Email:
        <input name="email" type="text" />
      </label>
      <label>
        isSoldier:
        <input name="isSoldier" type="checkbox" />
      </label>
      <button type="submit">Submit</button>
    </form>
  );
}