Registry / web-framework / final-form

final-form

JSON →
library5.0.0jsnpmunverified

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.

npm install final-form
INSTALL
IMPORT
SIG · FINAL-FORM
F
final-form
web-frameworkjavascriptv5.0.0
Install
Import
Disk
Pass rate
0/ 6
Env Coverage0 / 6
glibc
1822
musl
1822
Install & Compatibility
Where this runs
tested against v? · npm install
Install × environment matrix
Each cell = how many times install + import succeeded across repeated harness runs. Partial = flaky.
glibc = Debian/Ubuntu slim · musl = Alpine Linux
musl
node 18226 runs
build_error
glibc
node 18226 runs
build_error
Code
Verified usage

Verified import paths — ran on the pinned version, not inferred.

createForm
import { createForm } from 'final-form'
const createForm = require('final-form')
ESM is the recommended import style. CommonJS `require` is generally discouraged in modern applications and may lead to issues with bundlers or tree-shaking.
FormApi
import type { FormApi } from 'final-form'
import { FormApi } from 'final-form'
FormApi is a TypeScript type representing the form instance. It should be imported as a type for type-checking purposes only. Importing it as a value will result in a runtime error or unnecessary bundle size.
FieldState
import type { FieldState } from 'final-form'
import { FieldState } from 'final-form'
FieldState is a TypeScript type for the state of an individual field. Like FormApi, it should be imported as a type.

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();
Debug
Known issues
breakingVersion 5.0.0 converted the entire library from Flow to TypeScript. While no *intentional* API breaking changes were introduced, developers relying on Flow types or intricate type inference might experience minor issues or require adjustments to their TypeScript configurations. Always test thoroughly when upgrading.
fix
Review TypeScript definitions in your project, especially if you had custom type augmentations for previous Flow-typed versions. Ensure your `tsconfig.json` is compatible and rebuild your application.
affects: >=5.0.0
gotchaFinal Form's subscription model is powerful but requires careful selection of subscribed state. Subscribing to too much state can negate performance benefits, while subscribing to too little might cause components not to re-render when expected.
fix
Always explicitly define which form state properties (e.g., `{ values: true, errors: true, dirty: true }`) your component needs to re-render. Avoid subscribing to `everything: true` unless absolutely necessary for debugging or specific scenarios.
affects: >=4.0.0
gotchaAsynchronous validation in Final Form can sometimes lead to unexpected behavior, such as errors not clearing or validations running at incorrect times, especially if not handled correctly with debouncing or when field values change rapidly.
fix
Ensure your async validation logic correctly returns promises and handles their resolution/rejection. Review the official documentation on `asyncValidate` and consider debouncing your validation function for better user experience and to prevent validation 'races'.
affects: >=4.20.0
gotchaThe `allValues` argument for `FieldValidator` was made optional in v4.20.7, but this change was reverted in v4.20.9. This inconsistency might cause type errors or unexpected runtime behavior if your validation functions rely on its optionality or presence across these specific versions.
fix
If using versions 4.20.7 or 4.20.8, explicitly handle `allValues` as potentially undefined or ensure your validator functions are robust to its presence. For optimal type safety, upgrade to >=4.20.9 where `allValues` is consistently required or check documentation for current behavior.
affects: 4.20.7 - 4.20.8
Errors
Common errors & fixes
TS2345: Argument of type 'Partial<FormState<T>>' is not assignable to parameter of type 'FormSubscription'.
Attempting to pass a partial FormState object as a subscription parameter instead of a FormSubscription object.
fix
Ensure that the second argument to `form.subscribe` is a `FormSubscription` object, where keys are state properties and values are booleans indicating subscription interest, e.g., `{ values: true, errors: true }`.
TypeError: createForm is not a function
Incorrect CommonJS `require` syntax or mixing CommonJS with ESM in a module that expects ESM imports.
fix
Use ES module import syntax: `import { createForm } from 'final-form';`. If in a CommonJS-only environment (e.g., older Node.js scripts), ensure your bundler or environment correctly transpiles ESM or use dynamic import if supported.
Property 'someField' does not exist on type 'FormState<MyFormData>'. Did you mean 'values'?
Directly accessing field values on the `FormState` object rather than through the `formState.values` property.
fix
Access form values via `formState.values.someField` and errors via `formState.errors.someField`. `FormState` itself contains metadata about the form, not the field values directly.
Upgrade
Version history
5.0.0latest on npm
Audit
Dependencies

No dependency data recorded yet.

Agent activity
2 hits · last 30 days
node
2
Resources
final-form — npm install final-form · libregistry