Skip to content

feat: add useFormsy hook as alternative to withFormsy HOC #761

Description

@ThibautMarechal

Motivation

withFormsy is a class-component HOC that predates React hooks. It works, but comes with the friction typical of HOCs:

  • Prop origin opacity — readers can't tell which props come from the parent vs. formsy without reading the HOC source
  • TypeScript complexity — the return type references an internal type (WrapperProps) that is not portably nameable in declaration files (see Export WrapperProps from main entry to fix TS2883 in projects with declaration emit #759)
  • Wrapper hell — composing multiple HOCs creates deeply nested component trees in React DevTools
  • Class component internalswithFormsy is implemented as a class component, which is an increasingly rare pattern to maintain

The modern React idiom for sharing stateful logic is a hook. Formsy already exposes FormsyContext internally and all the logic in the HOC could be expressed as a useFormsy hook.

Proposed API

import { useFormsy } from 'formsy-react';

function MyInput({ name, label }: { name: string; label: string }) {
  const { value, setValue, errorMessage, showError, isPristine } = useFormsy<string>({ name });

  return (
    <div>
      <label>{label}</label>
      <input value={value ?? ''} onChange={(e) => setValue(e.target.value)} />
      {showError && <span>{String(errorMessage)}</span>}
    </div>
  );
}

The component is a plain function — no HOC wrapping, no prop injection, full type inference.

Design notes

  • useFormsy would consume FormsyContext (already exists) to register/deregister the field, sync value, and run validations — mirroring exactly what WithFormsyWrapper does today in the class component
  • name is passed directly inside the options object, not injected
  • withFormsy would not be removed — it stays for backward compatibility. useFormsy is an additive, opt-in API
  • The hook reuses the same validation logic already extracted in utils and validationRules

Backward compatibility

  • withFormsy is unchanged
  • useFormsy is a new export — no breaking change

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions