All questions

useForm

Premium

useForm

Forms are deceptively deep: you need current values, per-field errors from validation, which fields have been touched (so you don't show "Required" before the user has even reached the field), and an isSubmitting flag to disable the button during an async submit. useForm is a minimal version of the Formik/React-Hook-Form core — one hook that owns all four and wires up handleChange/handleBlur/handleSubmit.

Implement useForm({ initialValues, validate, onSubmit }). Return { values, errors, touched, isSubmitting, handleChange, handleBlur, handleSubmit, setFieldValue, reset }. Validate on change; on submit, validate everything, mark all fields touched, and only call onSubmit when there are no errors.

Signature

function useForm({ initialValues, validate, onSubmit }) {
  // returns { values, errors, touched, isSubmitting,
  //           handleChange, handleBlur, handleSubmit, setFieldValue, reset }
}

Examples

const f = useForm({
  initialValues: { email: '' },
  validate: (v) => (v.email.includes('@') ? {} : { email: 'Invalid email' }),
  onSubmit: (v) => api.subscribe(v),
});
<form onSubmit={f.handleSubmit}>
  <input name="email" value={f.values.email} onChange={f.handleChange} onBlur={f.handleBlur} />
  {f.touched.email && f.errors.email && <span>{f.errors.email}</span>}
  <button disabled={f.isSubmitting}>Subscribe</button>
</form>

Notes

  • validate(values) returns { field: message } for invalid fields ({} when valid); run it on change and on submit.
  • handleChange reads e.target (checkbox → checked, else value), updates that field, and re-validates.
  • touchedhandleBlur marks a field touched; handleSubmit marks all fields touched (so errors show after a submit attempt).
  • handleSubmitpreventDefault, validate; if there are errors, stop; otherwise set isSubmitting and await onSubmit(values), clearing the flag when done. Keep the handlers stable.

Unlock the solution & editor

  • Runnable editor + tests

    Solve in the browser with instant Jest feedback.

  • Detailed solutions

    Walkthroughs, edge cases, and complexity notes.

  • Multi-framework variants

    React, Vue, Vanilla, Angular — same question, different stacks.

Upgrade to Premium