Rooks
Form & File Handling

useFormState

Manages controlled form field state with value and onChange bindings.

About

React hook for comprehensive form state management with validation and error handling. Manages form values, errors, touched state, and submission.

Installation

npm install rooks

Usage

import { useFormState } from "rooks";

interface LoginForm {
  email: string;
  password: string;
  remember: boolean;
}

function LoginComponent() {
  const {
    values,
    errors,
    touched,
    isSubmitting,
    isValid,
    handleChange,
    handleSubmit,
    reset,
  } = useFormState<LoginForm>({
    initialValues: {
      email: "",
      password: "",
      remember: false,
    },
    validate: (name, value, values) => {
      if (name === "email" && !value.includes("@")) {
        return "Please enter a valid email address";
      }
      if (name === "password" && value.length < 6) {
        return "Password must be at least 6 characters";
      }
      return undefined;
    },
    onSubmit: async (values) => {
      console.log("Form submitted:", values);
      // Perform login
      await loginUser(values);
    },
  });

  return (
    <form onSubmit={handleSubmit}>
      <div>
        <label>Email:</label>
        <input
          name="email"
          type="email"
          value={values.email}
          onChange={handleChange}
        />
        {touched.email && errors.email && (
          <span style={{ color: "red" }}>{errors.email}</span>
        )}
      </div>

      <div>
        <label>Password:</label>
        <input
          name="password"
          type="password"
          value={values.password}
          onChange={handleChange}
        />
        {touched.password && errors.password && (
          <span style={{ color: "red" }}>{errors.password}</span>
        )}
      </div>

      <div>
        <label>
          <input
            name="remember"
            type="checkbox"
            checked={values.remember}
            onChange={handleChange}
          />
          Remember me
        </label>
      </div>

      <button type="submit" disabled={!isValid || isSubmitting}>
        {isSubmitting ? "Logging in..." : "Login"}
      </button>
      <button type="button" onClick={reset}>
        Reset
      </button>
    </form>
  );
}

API

Options

PropertyTypeDescription
initialValuesTInitial form values
validate(name, value, values) => string | undefinedValidation function for fields
onSubmit(values: T) => void | Promise<void>Callback when form is submitted with valid data

Return Value

Returns an object with the following properties:

PropertyTypeDescription
valuesTCurrent form values
errorsPartial<Record<keyof T, string>>Validation errors for each field
touchedPartial<Record<keyof T, boolean>>Touched state for each field
isSubmittingbooleanWhether the form is currently submitting
isValidbooleanWhether the form is valid
handleChange(event) => voidHandle input change events
handleSubmit(event) => voidHandle form submit events
setFieldValue(name, value) => voidSet a specific field value
setFieldError(name, error) => voidSet a specific field error
setFieldTouched(name, touched) => voidSet a specific field as touched
reset() => voidReset the form to initial values

Features

  • Complete form state - Values, errors, touched state, and submission status
  • Field validation - Validate individual fields on change
  • Form validation - Validate entire form on submit
  • Error tracking - Per-field error messages
  • Touched tracking - Know which fields the user has interacted with
  • Async submission - Support for async onSubmit handlers
  • Programmatic control - Manually set field values, errors, and touched state
  • TypeScript support - Full type safety with generics
  • Input type support - Handles text, checkbox, textarea, and select inputs

Validation

The validation function receives three parameters:

  1. name - The field name being validated
  2. value - The current value of the field
  3. values - All current form values

Return a string for validation errors, or undefined if valid.

validate: (name, value, values) => {
  if (name === "password" && value.length < 8) {
    return "Password must be at least 8 characters";
  }
  if (name === "confirmPassword" && value !== values.password) {
    return "Passwords do not match";
  }
  return undefined;
}

Use Cases

  • Login/registration forms
  • Multi-step forms
  • Profile update forms
  • Complex forms with cross-field validation
  • Forms with async submission
  • Forms requiring field-level validation feedback

On this page