CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-react-final-form

High performance subscription-based form state management for React

Pending
Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Pending

The risk profile of this skill

Overview
Eval results
Files

index.mddocs/

React Final Form

React Final Form is a high-performance, subscription-based form state management library for React applications. Built as a thin wrapper around Final Form, it provides efficient form handling through the Observer pattern with zero dependencies that affect bundle size and a tiny 3.0k gzipped footprint.

Package Information

  • Package Name: react-final-form
  • Package Type: npm
  • Language: TypeScript
  • Installation: npm install react-final-form

Core Imports

import { 
  Form, 
  Field, 
  FormSpy, 
  useForm, 
  useField, 
  useFormState,
  withTypes,
  version,
  all
} from "react-final-form";

// Import types from react-final-form
import type { 
  FormProps, 
  FieldProps, 
  FormSpyProps,
  FieldRenderProps,
  FormRenderProps,
  UseFieldConfig,
  UseFormStateParams,
  ReactContext,
  FormSpyPropsWithForm,
  FieldInputProps,
  RenderableProps,
  SubmitEvent,
  UseFieldAutoConfig
} from "react-final-form";

// Import types from final-form (peer dependency)
import type {
  FormApi,
  FormState,
  FieldState,
  FormSubscription,
  FieldSubscription,
  Config,
  Decorator,
  FieldValidator
} from "final-form";

For CommonJS:

const { 
  Form, 
  Field, 
  FormSpy, 
  useForm, 
  useField, 
  useFormState,
  withTypes,
  version,
  all
} = require("react-final-form");

Basic Usage

import React from "react";
import { Form, Field } from "react-final-form";

interface FormValues {
  firstName: string;
  lastName: string;
  email: string;
}

const onSubmit = (values: FormValues) => {
  console.log(values);
};

function MyForm() {
  return (
    <Form<FormValues>
      onSubmit={onSubmit}
      render={({ handleSubmit, form, submitting, pristine, values }) => (
        <form onSubmit={handleSubmit}>
          <Field name="firstName">
            {({ input, meta }) => (
              <div>
                <label>First Name</label>
                <input {...input} type="text" placeholder="First Name" />
                {meta.error && meta.touched && <span>{meta.error}</span>}
              </div>
            )}
          </Field>
          
          <Field name="email">
            {({ input, meta }) => (
              <div>
                <label>Email</label>
                <input {...input} type="email" placeholder="Email" />
                {meta.error && meta.touched && <span>{meta.error}</span>}
              </div>
            )}
          </Field>
          
          <button type="submit" disabled={submitting}>
            Submit
          </button>
          <button
            type="button"
            onClick={form.reset}
            disabled={submitting || pristine}
          >
            Reset
          </button>
        </form>
      )}
    />
  );
}

Architecture

React Final Form is built around several key components:

  • Form Component: Root form wrapper that provides form context and manages form state
  • Field Component: Individual field components that subscribe to specific field state
  • Hooks API: Modern React hooks for accessing form and field state
  • Subscription System: Opt-in subscriptions ensure only components requiring updates are re-rendered
  • Render Props: Flexible rendering patterns supporting both render props and children functions
  • Type Safety: Full TypeScript support with generic type preservation

Capabilities

Form Management

Core form wrapper component that provides form context, state management, and submission handling with efficient subscription-based updates.

const Form: <FormValues = Record<string, any>>(
  props: FormProps<FormValues>
) => React.ReactElement;

interface FormProps<FormValues = Record<string, any>>
  extends Config<FormValues>,
    RenderableProps<FormRenderProps<FormValues>> {
  subscription?: FormSubscription;
  decorators?: Decorator<FormValues>[];
  form?: FormApi<FormValues>;
  initialValuesEqual?: (
    a?: Record<string, any>,
    b?: Record<string, any>
  ) => boolean;
}

interface FormRenderProps<FormValues = Record<string, any>>
  extends FormState<FormValues> {
  handleSubmit: (
    event?: SubmitEvent
  ) => Promise<Record<string, any> | undefined> | undefined;
  form: FormApi<FormValues>;
}

Form Component

Field Management

Individual field components with subscription-based state management, validation, formatting, and parsing capabilities.

const Field: <
  FieldValue = any,
  T extends HTMLElement = HTMLElement,
  FormValues = Record<string, any>
>(
  props: FieldProps<FieldValue, T, FormValues>
) => React.ReactElement;

interface FieldProps<
  FieldValue = any,
  T extends HTMLElement = HTMLElement,
  FormValues = Record<string, any>
> extends UseFieldConfig,
    Omit<RenderableProps<FieldRenderProps<FieldValue, T>>, "children"> {
  name: string;
  children?: RenderableProps<FieldRenderProps<FieldValue, T>>["children"];
  [key: string]: any;
}

interface FieldRenderProps<
  FieldValue = any,
  T extends HTMLElement = HTMLElement,
  FormValues = any
> {
  input: FieldInputProps<FieldValue, T>;
  meta: {
    active?: boolean;
    data?: Record<string, any>;
    dirty?: boolean;
    dirtySinceLastSubmit?: boolean;
    error?: any;
    initial?: any;
    invalid?: boolean;
    length?: number;
    modified?: boolean;
    modifiedSinceLastSubmit?: boolean;
    pristine?: boolean;
    submitError?: any;
    submitFailed?: boolean;
    submitSucceeded?: boolean;
    submitting?: boolean;
    touched?: boolean;
    valid?: boolean;
    validating?: boolean;
    visited?: boolean;
  };
}

Field Component

Form State Observation

FormSpy component for observing form state changes without rendering form fields, perfect for external components that need form state updates.

const FormSpy: <FormValues = Record<string, any>>(
  props: FormSpyProps<FormValues>
) => React.ReactElement;

interface FormSpyProps<FormValues = Record<string, any>>
  extends UseFormStateParams<FormValues>,
    RenderableProps<FormSpyRenderProps<FormValues>> {}

interface FormSpyRenderProps<FormValues = Record<string, any>>
  extends FormState<FormValues> {
  form: FormApi<FormValues>;
}

Form Spy

Hooks API

Modern React hooks for accessing form context, field state, and form state with customizable subscriptions and full TypeScript support.

function useForm<FormValues = Record<string, any>>(
  componentName?: string
): FormApi<FormValues>;

function useField<
  FieldValue = any,
  T extends HTMLElement = HTMLElement,
  FormValues = Record<string, any>
>(
  name: string,
  config?: UseFieldConfig
): FieldRenderProps<FieldValue, T, FormValues>;

function useFormState<FormValues = Record<string, any>>(
  params?: UseFormStateParams<FormValues>
): FormState<FormValues>;

Hooks API

TypeScript Integration

Utility functions and type helpers for enhanced TypeScript support with strongly typed form and field components.

function withTypes<FormValues = Record<string, any>>(): {
  Form: React.ComponentType<FormProps<FormValues>>;
  FormSpy: React.ComponentType<FormSpyProps<FormValues>>;
};

const version: string;

const all: FormSubscription;

TypeScript Support

Core Types

interface FieldInputProps<
  FieldValue = any,
  T extends HTMLElement = HTMLElement
> {
  name: string;
  onBlur: (event?: React.FocusEvent<T>) => void;
  onChange: (event: React.ChangeEvent<T> | any) => void;
  onFocus: (event?: React.FocusEvent<T>) => void;
  value: FieldValue;
  checked?: boolean;
  multiple?: boolean;
  type?: string;
}

interface RenderableProps<T> {
  component?: React.ComponentType<any> | SupportedInputs;
  children?: ((props: T) => React.ReactNode) | React.ReactNode;
  render?: (props: T) => React.ReactNode;
}

interface SubmitEvent {
  preventDefault?: () => void;
  stopPropagation?: () => void;
}

interface UseFormStateParams<FormValues = Record<string, any>> {
  onChange?: (formState: FormState<FormValues>) => void;
  subscription?: FormSubscription;
}

interface UseFieldConfig extends UseFieldAutoConfig {
  subscription?: FieldSubscription;
}

interface UseFieldAutoConfig {
  afterSubmit?: () => void;
  allowNull?: boolean;
  beforeSubmit?: () => void | false;
  component?: RenderableProps<any>["component"];
  data?: Record<string, any>;
  defaultValue?: any;
  format?: (value: any, name: string) => any;
  formatOnBlur?: boolean;
  initialValue?: any;
  isEqual?: (a: any, b: any) => boolean;
  multiple?: boolean;
  parse?: (value: any, name: string) => any;
  type?: string;
  validate?: FieldValidator<any>;
  validateFields?: string[];
  value?: any;
}

interface ReactContext<FormValues = Record<string, any>> {
  reactFinalForm: FormApi<FormValues>;
}

interface FormSpyPropsWithForm<FormValues = Record<string, any>>
  extends FormSpyProps<FormValues> {
  reactFinalForm: FormApi<FormValues>;
}

type SupportedInputs = "input" | "select" | "textarea";

docs

field.md

form-spy.md

form.md

hooks.md

index.md

typescript.md

tile.json