Final Form

5.0.0 · active · verified Sun Apr 19

Final Form is a high-performance, framework-agnostic library for managing form state in JavaScript applications. It provides a subscription-based model, meaning components only re-render when the specific pieces of state they subscribe to change, leading to optimized performance. The current stable version is 5.0.0, which notably converted the entire codebase from Flow to TypeScript, enhancing developer experience for TypeScript users. While core API stability is maintained across minor versions, major versions are bumped cautiously, as seen with v5.0.0, to reflect significant internal changes. Key differentiators include its zero-dependency footprint, small bundle size (around 5.1kB gzipped), and its explicit opt-in subscription model, giving developers fine-grained control over re-renders, making it suitable for complex form interactions across various UI frameworks.

Common errors

Warnings

Install

Imports

Quickstart

This quickstart demonstrates how to create a basic form instance with initial values, onSubmit and validation logic, and subscribe to form state changes using `createForm` from `final-form`.

import { createForm } from 'final-form';

interface MyFormData {
  firstName: string;
  lastName: string;
  age: number;
}

const form = createForm<MyFormData>({
  initialValues: { firstName: 'John', lastName: 'Doe', age: 30 },
  onSubmit: async (values) => {
    await new Promise(resolve => setTimeout(resolve, 500));
    console.log('Form submitted with values:', values);
  },
  validate: (values) => {
    const errors: Partial<MyFormData> = {};
    if (!values.firstName) {
      errors.firstName = 'Required';
    }
    if (!values.lastName) {
      errors.lastName = 'Required';
    }
    if (values.age < 18) {
      errors.age = 'Must be 18 or older';
    }
    return errors;
  },
});

const unsubscribe = form.subscribe((formState) => {
  console.log('Form State Changed:', {
    values: formState.values,
    errors: formState.errors,
    valid: formState.valid,
    dirty: formState.dirty,
    submitting: formState.submitting,
  });
}, { values: true, errors: true, valid: true, dirty: true, submitting: true });

// Simulate user input
form.change('firstName', 'Jane');
form.change('age', 17);

// Simulate form submission
form.submit();

// Cleanup (in a real app, this would be on unmount)
// unsubscribe();

view raw JSON →