Rooks
HooksForm & File Handling

useFormState

Manages named form values, validation, touched state, and submission.

About

useFormState coordinates a record of controlled form values, field errors, touched flags, and synchronous or asynchronous submission.

Example

import { useState } from "react";
import { useFormState } from "rooks";

type SignupFields = {
  email: string;
  updates: boolean;
};

export default function SignupForm() {
  const [message, setMessage] = useState("");
  const form = useFormState<SignupFields>({
    initialValues: { email: "", updates: false },
    validate: (name, value) => {
      if (name === "email" && !String(value).includes("@")) {
        return "Enter a valid email address";
      }
      return undefined;
    },
    onSubmit: (values) => {
      setMessage(values.updates ? "Subscribed with updates" : "Subscribed");
    },
  });

  return (
    <form onSubmit={form.handleSubmit}>
      <label>
        Email
        <input
          name="email"
          value={form.values.email}
          onChange={form.handleChange}
        />
      </label>
      {form.touched.email && form.errors.email && (
        <p role="alert">{form.errors.email}</p>
      )}
      <label>
        <input
          name="updates"
          type="checkbox"
          checked={form.values.updates}
          onChange={form.handleChange}
        />
        Product updates
      </label>
      <button type="submit" disabled={form.isSubmitting}>
        Submit
      </button>
      <p>{message}</p>
    </form>
  );
}

Parameters

Pass an object with:

  • initialValues: required record that defines the field keys and starting values.
  • validate(name, value, values): optional function returning an error string or undefined.
  • onSubmit(values): optional function returning void | Promise<void>.

The source module declares option, result, and validator types, but the rooks entrypoint does not re-export them. Use inference or local shapes rather than importing those names.

Return value

The result contains values, errors, touched, isSubmitting, isValid, handleChange, handleSubmit, setFieldValue, setFieldError, setFieldTouched, and reset. handleChange supports input, textarea, and select change events. handleSubmit accepts a form submit event and returns void.

Behavior and lifecycle

handleChange uses checked for checkboxes and string value for every other control, marks the field touched, and validates it. The validator receives the next field value but the full values record from the previous render. Programmatic field setters do not automatically validate or mark fields touched. Submit prevents the default action, marks every current key touched, validates all fields, and calls onSubmit only when valid. isValid means the current error object has no keys.

A valid submission sets isSubmitting until the returned promise settles. Rejections and synchronous errors are not caught, and repeated submits are not blocked automatically. reset restores the latest initialValues captured by the hook and clears errors, touched flags, and submission state.

Compatibility and accessibility

The hook uses React state only and is safe during server rendering. It does not render labels, connect errors with aria-describedby, focus the first invalid field, parse numeric values, or disable duplicate submissions. The form must provide those behaviors.

On this page