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

Overview
Eval results
Files

form.mddocs/

Form Component

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

Capabilities

Form Component

The main Form component that wraps form elements and provides form state management through React context.

/**
 * Main form wrapper component providing form context and state management
 * @param props - Form configuration and render props
 * @returns React element with form context
 */
const Form: <FormValues = Record<string, any>>(
  props: FormProps<FormValues>
) => React.ReactElement;

interface FormProps<FormValues = Record<string, any>>
  extends Config<FormValues>,
    RenderableProps<FormRenderProps<FormValues>> {
  /** Form state subscription configuration */
  subscription?: FormSubscription;
  /** Form decorators for additional functionality */
  decorators?: Decorator<FormValues>[];
  /** External form API instance */
  form?: FormApi<FormValues>;
  /** Custom equality function for initial values comparison */
  initialValuesEqual?: (
    a?: Record<string, any>,
    b?: Record<string, any>
  ) => boolean;
}

interface FormRenderProps<FormValues = Record<string, any>>
  extends FormState<FormValues> {
  /** Form submission handler with event handling */
  handleSubmit: (
    event?: SubmitEvent
  ) => Promise<Record<string, any> | undefined> | undefined;
  /** Form API instance for programmatic control */
  form: FormApi<FormValues>;
}

Usage Examples:

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

// Basic form with render prop
function BasicForm() {
  return (
    <Form
      onSubmit={(values) => console.log(values)}
      render={({ handleSubmit, pristine, invalid }) => (
        <form onSubmit={handleSubmit}>
          {/* form fields */}
          <button type="submit" disabled={pristine || invalid}>
            Submit
          </button>
        </form>
      )}
    />
  );
}

// Form with initial values and validation
function ValidatedForm() {
  const validate = (values: any) => {
    const errors: any = {};
    if (!values.firstName) {
      errors.firstName = "Required";
    }
    return errors;
  };

  return (
    <Form
      onSubmit={(values) => console.log(values)}
      initialValues={{ firstName: "John" }}
      validate={validate}
      render={({ handleSubmit, form, submitting, values }) => (
        <form onSubmit={handleSubmit}>
          {/* form fields */}
          <button type="submit" disabled={submitting}>
            Submit
          </button>
          <button type="button" onClick={form.reset}>
            Reset
          </button>
          <pre>{JSON.stringify(values, null, 2)}</pre>
        </form>
      )}
    />
  );
}

// Form with children function
function ChildrenForm() {
  return (
    <Form onSubmit={(values) => console.log(values)}>
      {({ handleSubmit, submitting }) => (
        <form onSubmit={handleSubmit}>
          {/* form fields */}
          <button type="submit" disabled={submitting}>
            Submit
          </button>
        </form>
      )}
    </Form>
  );
}

Form Subscription Configuration

The Form component supports customizable subscriptions to optimize rendering performance by only updating when specific form state changes occur.

interface FormSubscription {
  active?: boolean;
  dirty?: boolean;
  dirtyFields?: boolean;
  dirtySinceLastSubmit?: boolean;
  error?: boolean;
  errors?: boolean;
  hasSubmitErrors?: boolean;
  hasValidationErrors?: boolean;
  initialValues?: boolean;
  invalid?: boolean;
  modified?: boolean;
  modifiedSinceLastSubmit?: boolean;
  pristine?: boolean;
  submitError?: boolean;
  submitErrors?: boolean;
  submitFailed?: boolean;
  submitSucceeded?: boolean;
  submitting?: boolean;
  touched?: boolean;
  valid?: boolean;
  validating?: boolean;
  values?: boolean;
  visited?: boolean;
}

Usage Example:

import { Form } from "react-final-form";

function OptimizedForm() {
  return (
    <Form
      onSubmit={(values) => console.log(values)}
      subscription={{ submitting: true, pristine: true, invalid: true }}
      render={({ handleSubmit, submitting, pristine, invalid }) => (
        <form onSubmit={handleSubmit}>
          {/* Only re-renders when submitting, pristine, or invalid changes */}
          <button type="submit" disabled={submitting || pristine || invalid}>
            Submit
          </button>
        </form>
      )}
    />
  );
}

Form Configuration Options

The Form component accepts all configuration options from the underlying Final Form library through the Config interface.

interface Config<FormValues = Record<string, any>> {
  /** Debug mode for development */
  debug?: (state: FormState<FormValues>, action: string) => void;
  /** Whether to destroy field state when field is unregistered */
  destroyOnUnregister?: boolean;
  /** Initial form values */
  initialValues?: Partial<FormValues>;
  /** Whether to keep dirty values when reinitializing */
  keepDirtyOnReinitialize?: boolean;
  /** Custom mutators for form state manipulation */
  mutators?: Record<string, Mutator<FormValues>>;
  /** Form submission handler */
  onSubmit: (
    values: FormValues,
    form: FormApi<FormValues>,
    callback?: (errors?: SubmissionErrors) => void
  ) => SubmissionErrors | Promise<SubmissionErrors> | undefined | void;
  /** Form-level validation function */
  validate?: (values: FormValues) => ValidationErrors | Promise<ValidationErrors>;
  /** Values to validate on each change */
  validateOnBlur?: boolean;
}

Error Handling

Forms provide comprehensive error handling through multiple error sources and clear error state management.

interface FormState<FormValues = Record<string, any>> {
  /** Current form validation errors */
  errors?: ValidationErrors;
  /** Submission errors from the last submit attempt */
  submitErrors?: SubmissionErrors;
  /** General submission error */
  submitError?: any;
  /** Whether the last submission failed */
  submitFailed?: boolean;
  /** Whether the last submission succeeded */
  submitSucceeded?: boolean;
  /** Whether form has validation errors */
  hasValidationErrors?: boolean;
  /** Whether form has submission errors */
  hasSubmitErrors?: boolean;
}

type ValidationErrors = Record<string, any>;
type SubmissionErrors = Record<string, any>;

Usage Example:

function ErrorHandlingForm() {
  const onSubmit = async (values: any) => {
    // Simulate server validation
    if (values.email === "taken@example.com") {
      return { email: "Email already taken" };
    }
    // Success case
    console.log("Submitted:", values);
  };

  return (
    <Form
      onSubmit={onSubmit}
      render={({ handleSubmit, submitError, hasSubmitErrors, errors }) => (
        <form onSubmit={handleSubmit}>
          {submitError && <div className="error">{submitError}</div>}
          {hasSubmitErrors && (
            <div className="error">Please fix the errors below</div>
          )}
          {/* form fields */}
        </form>
      )}
    />
  );
}

Install with Tessl CLI

npx tessl i tessl/npm-react-final-form

docs

field.md

form-spy.md

form.md

hooks.md

index.md

typescript.md

tile.json