final-form-set-field-data

A Final Form mutator that lets you attach and merge arbitrary metadata onto individual form fields.

Library
npm
v1.0.2
39stars
MIT License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
28/100Needs Attention
Development Activity4
Maintenance20
Community16
Maturity60
Momentum12

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
45/100Fair
Architecture55
Code Quality60
Innovation25
Learning Curve40

final-form-set-field-data is a small mutator plugin for the Final Form form-state library. It adds a single setFieldData mutator that merges an arbitrary object of metadata into a specific field’s data property, which Final Form already exposes to subscribers via fieldState.data.

This is useful for attaching UI-only concerns to a field — such as whether it should currently be visible, disabled, marked as “just validated”, or tagged with any other app-specific flag — without threading that state through your own separate store or re-deriving it from the field’s value on every render. Because it plugs into Final Form’s existing mutator and subscription system, consuming components only need to subscribe to data to react to changes.

The package is deliberately minimal: it ships one function, has no runtime dependencies beyond the final-form peer dependency, and is maintained under the official final-form GitHub organization alongside the core library and its other companion mutators (e.g. final-form-arrays, final-form-calculate).

What You Get

  • A single setFieldData(name, data) mutator you register with createForm({ mutators: { setFieldData } })
  • Shallow-merge semantics — calling it repeatedly merges new keys into the field’s existing data object rather than replacing it
  • No-op safety — calling it for a field name that doesn’t exist in form state does nothing instead of throwing
  • Direct integration with Final Form’s existing field subscription model via fieldState.data
  • A tiny, dependency-free implementation (only final-form as a peer dependency) with both CommonJS and ES module builds

Common Use Cases

  • Marking a field as “just validated” or “touched via autofill” to drive a transient UI highlight
  • Storing per-field UI flags such as visible, disabled, or collapsed that are computed outside the normal value/validation flow
  • Tagging a field with metadata from an async lookup (e.g. an address-autocomplete suggestion source) for the rendering component to read
  • Coordinating custom field-level UI state across sibling components that all subscribe to the same field’s data

Under The Hood

Architecture The entire package is two files — src/index.js re-exporting src/setFieldData.js — with no internal layering, since the whole surface area is a single Final Form mutator matching the library’s Mutator type signature (args, state, tools) => void. setFieldData destructures [name, data] from args, looks up state.fields[name] directly on Final Form’s own mutable internal state object, and shallow-merges into field.data ({ ...field.data, ...data }), silently no-op’ing if the field isn’t registered. There’s no dependency injection, no internal composition, and no data flow beyond this one side-effecting mutation against the host library’s state tree — the package’s only job is to slot into Final Form’s existing mutator contract, so there is nothing that would “break” beyond needing to track whatever MutableState/Mutator shape a future Final Form major version exposes.

Tech Stack Written in Flow-typed JavaScript (// @flow pragmas plus a hand-written index.js.flow declaration) and built with Rollup (rollup.config.js) into CommonJS, ES module, and UMD bundles via rollup-plugin-babel and Babel’s @babel/preset-env/@babel/preset-flow. Scripts are orchestrated through nps/nps-utils rather than raw npm scripts, bundle size is enforced with bundlesize against the built UMD/ES/CJS artifacts, and the only runtime relationship is a final-form peer dependency (no runtime dependencies of its own). CI runs on Travis (.travis.yml), with husky + lint-staged running Prettier and ESLint on commit.

Code Quality A single Jest test file (src/setFieldData.test.js) exercises the mutator directly: it verifies the no-tool-calls contract (Final Form passes getIn/setIn/changeValue/shallowEqual helpers the mutator never touches), correct merge behavior, preservation of existing sibling fields, and the no-op path for an unregistered field name — solid coverage given the function’s small surface area, though it’s the only source file under test since it’s also the only source file. Typing is via Flow rather than TypeScript, and ESLint (eslint-config-react-app) plus Prettier are wired into precommit via lint-staged, but there is no evidence of a CI-enforced type-check step beyond what Travis runs.

What Makes It Unique There is no novel technical approach here — it’s a minimal, intentionally boring adapter that takes advantage of a capability Final Form’s mutator/fieldState.data system already exposes. Its value is entirely in scope discipline: it does one merge operation and nothing else, matching the pattern of the other official final-form-* companion mutators (final-form-arrays, final-form-calculate) rather than introducing new architecture or techniques.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search