Atlas expedition

The React form-library landscape in 2026: RHF still wins, TanStack Form is the real challenger, Formik is a zombie

React Hook Form (v7.81.0, 58M weekly downloads, v8 in beta) remains the default; TanStack Form 1.33.2 is the credible challenger with a framework-agnostic core and better path types but self-admitted verbosity; Conform owns progressive-enhancement forms; Formik is a zombie and React Final Form is in maintenance limbo.

109 sources ~21 min read #4 react · forms · typescript · react-hook-form · tanstack-form · conform · formik · library-comparison

Decision. Default to React Hook Form ⭐ 44.8k (Jul 2026) — 7.81.0 shipped 2026-07-05, 58.0M weekly downloads, 3 open issues, and a v8 beta with first-class React Compiler support [1] [2] [3] ⭐ 44.8k [5]. Reach for TanStack Form ⭐ 6.6k (1.33.2) when you need a genuinely framework-agnostic core, honest deep-path/array typing, or first-party Next/Start/Remix server-function adapters — and accept the verbosity its own docs admit to [6] [69]. Reach for Conform ⭐ 2.6k only when progressive enhancement / FormData-first is a requirement, not a preference [52]. Formik ⭐ 34.3k is a zombie: zero commits in the six months to 2026-07-13, 704 open issues, and its author says on the record he stopped maintaining it in 2020 [15] ⭐ 34.3k [83]. React Final Form ⭐ 7.4k is in maintenance limbo — one bug-fix burst per year, no modern-React story [21] ⭐ 7.4k.

The scoreboard (all figures pulled from the npm registry + GitHub API on 2026-07-13)

Library Latest (release date) ⭐ Stars Weekly npm Open issues / PRs Commits, last 6 mo Verdict
React Hook Form [1] 7.81.0 (2026-07-05); 8.0.0-beta.3 (2026-07-10) 44.8k [3] ⭐ 44.8k 58.0M [2] 3 / 42 175 ✓ Dominant, accelerating
TanStack Form [6] 1.33.2 (2026-07-13) 6.6k [8] ⭐ 6.6k 2.0M [7] 91 / 60 142 ✓ Healthy, post-v1
Conform [10] 1.19.4 (2026-06-07) 2.6k [12] ⭐ 2.6k 241k [11] 45 / 8 72 ✓ Alive, bus-factor 1
Formik [13] 2.4.9 (2025-11-10) 34.3k [15] ⭐ 34.3k 4.3M [14] 704 / 132 0 ✗ Zombie
React Final Form [19] 7.0.1 (2026-05-05) 7.4k [21] ⭐ 7.4k 551k [20] 360 / 15 24 (bursty) ⚠ Maintenance limbo
RVF [24] ⭐ 972 8.1.3 (2026-07-04) 972 31k 18 / — ⚠ Tiny but current
Formisch [108] 1.0.0-rc.0 (2026-06-23) 1.0k [97] ⭐ 1.0k 2.5k ⚠ Too new to bet on

RHF outweighs everything else combined by roughly 8×. Its 3-open-issue backlog at 44.8k stars is the standout maintenance signal in the set [3] ⭐ 44.8k.

TanStack Form has been API-stable since v1.0 on 2025-03-02 [68]; its cadence has slowed from ~8–9 releases/month in 2025 to ~3 in 2026 — post-v1 stabilisation, not decay, given 142 commits in H1 [9] ⭐ 6.6k. Its 91-issue/60-PR backlog against 6.6k stars is proportionally far worse than RHF’s: a small-team-under-load signal, and the thing to price in if you adopt it.

Do not quote the form-library usage percentages attributed to “State of React 2025” — e.g. the widely-repeated “TanStack Form 21% usage, up 8 positions” [27]. The primary survey has no form-library question at all: its library sections are UI, State Management, Data Loading, Back-End, and Other Tools (testing, renderers, schema & validation, auth, mobile) [26] [28]. The survey is real; those percentages are not attributable to it. Use npm/GitHub numbers.

Dead, dying, alive

Formik — zombie. Last release 2.4.9 on 2025-11-10; the last feature release was 2.4.0 in May 2023 [13]. The 2.4.8/2.4.9 pair were React-19 JSX-namespace type patches published by the github-actions bot, not a human [16] ⭐ 34.3k. Zero commits between 2026-01-13 and 2026-07-13. The repo is not archived and there is no official notice; the community issue “Is Formik no longer maintained?” (opened Aug 2022) is still open with no maintainer reply [17] ⭐ 34.3k, as is its successor, literally titled “The best Form Library for react is abandoned?” [79] ⭐ 34.3k. Jared Palmer on X: “I haven’t maintained Formik since 2020” — the React-19 release was a Copilot dogfooding exercise [83]. Collaborator johnrom: “I would move on to React Hook Form if you’re starting fresh” [84] ⭐ 34.3k. It still pulls 4.3M weekly downloads on pure legacy inertia [14].

React Final Form — limbo, not death. After a 3-year gap, the final-form core [22] ⭐ 3.0k shipped 5.0.0 (2025-06-07), converting Flow→TypeScript with no intended breaking changes, and 5.0.1 (2026-05-05) was “a big batch of bug fixes that have accumulated” [23] ⭐ 3.0k [18]. Bursty, not sustained: react-final-form had 0 commits in H2-2025 and 24 in H1-2026, with 360 open issues nobody works [21] ⭐ 7.4k. 7.0.1 was published by an account named erikras-richard-agent, not Erik Rasmussen personally [19]. Architecturally frozen: no React 19, no Server Actions, no compiler story. Legacy-only.

HouseForm — dead (last release 2024-02-23) [25].

Bundle size — measured, not quoted

Blog-post numbers (the perennial “RHF is 8.5 kB”) are stale. These were measured on 2026-07-13 from two independent sources; they disagree by 1.5–3.3 kB, which is itself the honest answer.

Package (latest) Bundlephobia min+gzip bundlejs gzip (realistic import set) Runtime deps
react-hook-form@7.81.0 12.87 kB [29] 15.8 kB [37] 0 [44]
@tanstack/react-form@1.33.2 17.84 kB [30] 20.4 kB [38] 2 direct (form-core, react-store) [42]; + store, pacer-lite, use-sync-external-store transitively [30]
@conform-to/react@1.19.4 10.61 kB [31] 12.1 kB [39] @conform-to/dom
formik@2.4.9 13.12 kB [32] 16.4 kB [40] 8, incl. both lodash and lodash-es [43]
react-final-form@7.0.1 + final-form@5.0.1 3.96 + 6.89 = 10.85 kB [33] [34] 13.5 kB [41] @babel/runtime
@formisch/react@1.0.0-rc.0 6.39 kB (21.3 kB with Valibot) [97] ⭐ 1.0k valibot

These numbers are contested, and you should know by how much. Two of the better 2026 comparison posts measure TanStack Form as smaller than RHF — splitforms (esbuild, May 2026) gives TanStack ~6 kB vs RHF ~9 kB [54], LogRocket gives 9.6 vs 10.7 kB [87] — the inverse of the table above. The likely explanation is tree-shaking depth: @tanstack/form-core shakes hard when you import a narrow surface, while Bundlephobia measures the whole published package. Read the spread, not the ranking: every modern option lands somewhere in 6–21 kB, and nobody should choose a form library on 5 kB.

Because the size argument is dead. @hookform/resolvers is 0.55 kB [35], while zod@4 is 61.79 kB untreeshaken [36] — a real Zod import shakes down well below that, but even conservatively the schema library is the same order of magnitude as, or larger than, the form library. The 5 kB spread between form libraries is not a decision input. And RHF is not meaningfully smaller than Formik in 2026 — 12.87 vs 13.12 kB [29] [32] — despite RHF’s own FAQ still advertising a react-hook-form@7.27.0 8.5KB vs formik@2.1.4 15KB comparison built on 2022 versions [45]. The real win over Formik is the render model, not the bundle.

Conform is the smallest complete option and, being FormData-first, can run the same schema server-side and ship no client validator at all — an option the client-state libraries don’t structurally have [52] [57]. (TanStack’s createServerValidate also validates server-side [101] ⭐ 6.6k, but it still ships the client form model.)

Controlled vs uncontrolled, and what it actually costs

The axis that actually separates these libraries. Note the distinction the marketing blurs: “no re-render” always means no form-level re-render. It does not always mean no field-level re-render.

Library State lives in Keystroke re-renders… Escape hatch (and its footgun)
React Hook Form DOM node + internal object, outside React state; register captures a ref Nothing. The DOM node is written directly; no component renders [45]. ⚠ A Controller-wrapped field is controlled → that field renders useWatch/useFormState isolate subscriptions to the calling component; watch() re-renders the whole form — the source of most perf complaints [47] [48] ⭐ 44.8k
TanStack Form External TanStack Store, read via useSyncExternalStore The one <form.Field> subtree. Fields are controlled render-props (value={field.state.value} onChange={…field.handleChange}) [96] — the form component itself does not render [50] form.Subscribe re-renders only its subtree; useStore/useSelector without a selector re-renders the host component on any state change — same footgun as watch(), different name [50]
Conform The DOM; values read via FormData on demand [52] Nothing. Inputs stay native and uncontrolled; renders happen on validation events (blur/submit), not on input ✗ None available: no watch equivalent, so cross-field derived UI mid-typing is awkward [57]
Formik One controlled values object in React context The whole form. setState per keystroke; issue #3400 measures 3 renders on a single keystroke [49] ⭐ 34.3k ✗ None. Architectural, and it multiplies with field count
React Final Form final-form observer core Depends on the subscription you declare ⚠ The default is pessimistic: “If no subscription is provided, it will default to subscribing to all form state changes” [53] — an unconfigured RFF form gets Formik-grade renders

So the honest ordering per keystroke is: RHF (native input) = Conform: 0 renders < TanStack Form: 1 field subtree < Formik: the entire form. RHF’s zero collapses to TanStack’s one the moment a field needs Controller — which, with MUI/AntD/Radix components that don’t expose a native input’s value/onChange contract, is every field. That is the single most under-reported fact in this comparison: for a component-library-heavy app, RHF’s uncontrolled advantage largely evaporates [48] ⭐ 44.8k. (UI-kit wiring is a sibling angle in this expedition; treat it as a real selection input, not a footnote.)

There is no credible cross-library benchmark in 2025–2026. Every “comparison” post is qualitative [54] [55] [58]. RHF’s own benchmark repo — the one its FAQ links — is bluebill1049/react-hook-form-performance-compare, ⭐ 33, measuring mount time under 6× throttle (RHF 3800 ms, Formik 5800 ms, Redux Form 16000 ms) against a Redux Form straw man, with no TanStack or Conform entrant [46] ⭐ 33. Treat “RHF is fastest” as unverified against its actual 2026 rivals.

The perf conclusion that matters: at scale all three modern libraries are fast by default and slow by misuse, and the variable is subscription placement, not library choice — the RHF maintainer’s guidance on the canonical blowup (a large form with a root-level watch + Controller-wrapped AntD inputs) is “subscribe as deep down the tree as possible” [48] ⭐ 44.8k. Every one of these libraries has that same trap under a different name.

TypeScript inference — where each one actually breaks

Library Type source of truth Deep paths / arrays / unions Where it leaks
React Hook Form The hand-written useForm<T> genericnot the resolver schema; nothing enforces they agree Path<T> is an eagerly-computed string-literal union with a recursion cut-off (AnyIsEqual), and non-tuple arrays index as ArrayKey = number, so items.${number}.name is accepted with no index checking [60] [61] FieldValues = Record<string, any> [59]useFormContext returns any errors. Maintainer: “a current limitation with V7, fixed in the next major” — and v8 is still not GA [62] ⭐ 44.8k
TanStack Form defaultValues — the schema is validated against, but types don’t come from it [67] Best path machinery in the set: DeepKeysAndValues indexes array elements properly, handles tuples, distributes over unions, propagates parent nullability [70] Optional/union fields need a defaultValue expressing their full range or inference is wrong; unions need manual casts in onChange [82]
Conform The schema (useForm<Schema, FormValue, FormError>) — genuinely single-source No string-path union at all: FieldName is a branded string carrying phantom types, so names are produced (fields.email.name) via getFieldset()/getFieldList() [75] [76]. Discriminated unions handled explicitly by Combine<T> Sidesteps TS-perf and depth limits entirely — the strongest inference story, at the cost of the FormData straitjacket
Formik Nothing FieldProps<V = any, FormValues = any>, name: string [77] ✗ No path inference, no schema inference, no field-array typing. The TS guide only ever shows manually-supplied generics [78]
React Final Form Nothing FieldProps has _FormValues as a phantom (unused) parameter, name: string, and an [key: string]: any index signature that swallows typos [80] withTypes<FormValues>() types Form/FormSpy but not Field [81]. Worst TS story of the five

Two concrete RHF footguns an expert will hit. (1) The stringly-typed contract breaks at runtime: a field typed number silently becomes a string when edited, and TS cannot catch it — maintainer-confirmed [93] ⭐ 44.8k. (2) Generic field wrappers broke under Zod v4: constraining TSchema extends z.ZodType makes z.infer<TSchema> resolve to unknown“Type ‘unknown’ does not satisfy constraint ‘FieldValues’“; the current workaround is to constrain to z.core.$ZodType<any, any> [63] ⭐ 44.8k. Transforming schemas also force useForm<z.input<S>, unknown, z.output<S>> [64] ⭐ 44.8k.

And TanStack’s “you never pass a generic” claim breaks the moment you factor out a reusable field component. Its own docs concede “a common criticism of TanStack Form is that it is verbose out-of-the-box”, warn that the context escape hatch “will not warn you when the types do not align. You risk runtime errors”, and note that chaining AppForm extensions “can lead to decreases in TypeScript performance” [69]. Community: “I can’t figure out how to properly type form or field… you have to pass 10 type arguments”; maintainer Balastrong replies that a recommended wrapper pattern is still wanted [71] ⭐ 6.6k. The sanctioned createFormHook + withForm answer still pushes you toward AnyFormApi/AnyFieldApi, “where type safety is lost” [72].

Ranking. End-to-end schema→name→value inference: Conform ≥ TanStack Form > RHF ≫ Formik ≈ React Final Form. For reusable generic field components all of them degrade, but not equally: TanStack is the least bad, because createFormHook/withForm is at least a sanctioned, documented path [69] — RHF has no equivalent and its useFormContext type loss is a known v7 limitation deferred to a v8 that has not shipped [62] ⭐ 44.8k.

Headless-ness and framework coupling

Library Headless? Structure it imposes Framework-agnostic core?
React Hook Form ✓ Fully Uncontrolled/ref model; non-native components must go through Controller ✗ React-only
TanStack Form ✓ Fully Render-prop <form.Field> scaffolding per field — the verbosity tax [69] The only real one. @tanstack/form-core + 7 adapters; react/vue/solid/svelte/angular all at 1.33.2, ⚠ preact lags at 1.30.2 and lit at 1.25.2 [73]
Conform ✓ Fully (least markup opinion) ⚠ Everything must be expressible as FormData; non-native components (Radix/shadcn selects) bridge to a hidden native input via useControl [52] @conform-to/dom exists but only a React adapter ships [10] — and it couples upward to Remix/Next server actions instead [74]
Formik ~ Partly Ships <Field>, <Form>, <ErrorMessage> components ✗ React-only
React Final Form ✓ Fully Subscription-based render props ✓ Real final-form core with multiple bindings — but stagnant [18]

⚠ TanStack’s own comparison table marks RHF as “No” on React Compiler and SSR [51]. That is contradicted by RHF’s shipped v8 beta, whose headline feature is React Compiler support with no config [5]. Read it as marketing.

Validation layer and React 19 fit

Library Standard Schema React 19 / Server Functions Best runtime home
TanStack Form Native — schema goes straight on validators, no adapter package [100] ⭐ 6.6k ✓ Best-in-class: dedicated @tanstack/react-form-{nextjs,start,remix} packages, createServerValidate/onServerValidate, and a documented useActionState + useTransform/mergeForm bridge [101] ⭐ 6.6k Any meta-framework
React Hook Form ✓ via @hookform/resolvers/standard-schema (5.4.0) [65] ⭐ 2.3k [66] [102] No official position. The “React v19” discussion (#11832, opened Apr 2024) is still Unanswered in 2026 [103] ⭐ 44.8k. Its <Form action> + progressive: true POSTs to an HTTP endpoint, not a React Server Function [104]. Bolted onto useActionState it needs hacks (form clears on repeat submit with unchanged data) [105] SPA / client-heavy
Conform ✓ Advertised; the future/useForm rewrite takes any Standard Schema directly [106] ⭐ 2.6k It is the premise. Same schema in the server action (parseWithZod(formData, {schema})) and client (useForm({lastResult})) — client/server validation cannot drift; works with JS off [52] [74] Next App Router / React Router
Formik ✗ Yup-centric
React Final Form

Standard Schema is the common interface Zod/Valibot/ArkType/Effect now implement [109]; which schema library you pick is a sibling question — what matters here is that only TanStack Form and Conform consume it with zero adapter code, while RHF needs @hookform/resolvers (0.55 kB, so this is ergonomics, not weight).

Migration cost

Path Effort Codemod What breaks
Formik → RHF Moderate, mechanical, form-by-form ✗ None exists [86] ⭐ 26 Mental-model flip: controlled values → uncontrolled refs. <Formik>/useFormik()useForm(), <Field>register, useField()useController(), useFormikContext()useFormContext/useWatch. Live values need useWatch(). The two libs can coexist app-wide but not inside one form, so shared field components must be forked [85] ⭐ 22
Formik → TanStack Form Moderate — ⚠ not harder than Formik → RHF Both are <Field>-render-prop + controlled-value models, so the shape survives: <Field name><form.Field name children={(field)=>…}>, valuesfield.state.value, Yup schema→validators (Standard Schema, no adapter) [96] [100] ⭐ 6.6k
RHF v7 → v8 (beta) Small, ~5 mechanical edits register passes the real ref; useFieldArray idkey, keyName removed; watch(callback)subscribe(); setValue no longer overwrites field arrays → replace() [5]
RHF → TanStack Form Rewrite of the form layer ✗ No official guide — TanStack ships only a comparison page [51] register() string paths → <form.Field name validators children={(field) => …}> render props with manual field.state.value / field.handleChange. Every input component gets rewritten; validation moves from one resolver to per-field validators [96]
React Final Form → RHF Moderate; closest exit from RFF RFF’s <Field> render-prop → register/useController; subscription objects → useWatch/useFormState. You gain a TS story RFF never had [80]. ⚠ If you rely on the final-form core outside React, TanStack Form is the like-for-like target instead [18]
anything → Conform ⚠ Rewrite + server rework You surrender client-owned form state. Needs a server action / Remix-style route action to submit to; in plain Vite+React “the ergonomics suffer because there’s no server action equivalent” [92]

The only real automated tool is @hookform/codemod — and it only does v6→v7, last released Aug 2021 [86] ⭐ 26. Nothing else in this matrix has a codemod, so every migration is hand-work priced per form.

Counter-intuitive, and the most actionable line in this table: Formik → TanStack Form is conceptually closer than RHF → TanStack Form, because Formik and TanStack share the <Field>-render-prop + controlled-value model that RHF’s register inverts [96] [85] ⭐ 22. If you’re escaping Formik and were going to touch every field anyway, TanStack is not a bigger lift than RHF — it’s a different one, and the usual “Formik→RHF is the obvious path” advice quietly assumes otherwise.

Pick this if…

React Hook Form — the default, and the burden of proof is on anything else. Pick it if you’re building a SPA or a client-heavy app, you want the biggest ecosystem (58M weekly downloads means every edge case is already answered on Stack Overflow) [2], and you can live with stringly-typed paths. ⚠ Plan for v8: it’s in public beta with breaking changes and no GA date [4] ⭐ 44.8k [5].

TanStack Form — pick it if any of: (a) you ship the same form logic to more than one framework — it’s the only library that genuinely delivers this, with 7 adapters off one core (⚠ react/vue/solid/svelte/angular move together; preact and lit lag a few minors) [73]; (b) you have deeply nested / array-heavy forms where RHF’s ${number} index-less paths hurt [70]; (c) you’re already in the TanStack ecosystem or on TanStack Start; (d) you want first-party Server-Function wiring rather than community glue [101] ⭐ 6.6k. ⚠ Budget for building a createFormHook wrapper layer on day one — the raw API is verbose by the maintainers’ own admission [69], and its 91-issue/60-PR backlog on a small team is the risk to price in [8] ⭐ 6.6k.

Conform — pick it if progressive enhancement is a requirement (forms must work with JS disabled), or you’re on Next App Router / React Router v7 and want one schema that provably cannot drift between client and server [52] [74]. ⚠ Don’t pick it for a multi-step wizard with cross-field live previews — there is no watch and no client value store to hang derived UI off [57]. Bus-factor 1, 241k weekly downloads: a thin ecosystem when you hit an edge [11].

Formik — never, for new work. Its author and its collaborator both say so [83] [84] ⭐ 34.3k. If you have it, the only question is migration budget; it is not a security or correctness emergency, so migrate opportunistically, form by form.

React Final Form — only if you already have it and it works. No React 19 story, no compiler story, worst TS story, 360 stale issues [21] ⭐ 7.4k.

No library at all — a real option for small forms (the Next-focused guides draw the line at roughly 1–5 fields) [92] [54], and it just got more legitimate: shadcn/ui went form-agnostic in Oct 2025, with a <Field> family supporting RHF, TanStack Form, React 19 useActionState and custom [90] ⭐ 119k [91]. One of the biggest structural reasons RHF was the default — “shadcn’s <Form> is an RHF wrapper” — no longer holds. The critique that form libraries “re-create and manage the entire form’s state in a separate JS object” instead of using FormData and ValidityState has more teeth now than it did in 2023 [94]. A sibling angle in this expedition covers React’s native form primitives in depth.

RVF — the option nobody names. It occupies Conform’s progressive-enhancement niche with a more conventional API, ships current (8.1.3, 2026-07-04), and is the fallback if Conform’s bus-factor-1 risk is disqualifying. ⚠ But at 972 stars and 31k weekly downloads it trades one bus-factor problem for a smaller one [24] ⭐ 972.

Sentiment, attributed

  • Aggregator/blog consensus (vendor-blog / news): pkgpulse, splitforms, LogRocket all land on the same verdict — “React Hook Form remains the default choice for most React applications in 2026” [95] [54]; TanStack only for complex/nested forms or when already in its ecosystem [87].
  • HN practitioner who did RHF → TanStack (forum): “We started with react-hook-form and switched to Tanstack Form” — but reports that TanStack’s dirty-tracking breaks when default state changes and type inference degrades on complex array types, forcing custom code [88].
  • HN practitioner stuck on Formik (forum): “It’s outdated and hasn’t seen a real commit in years… its lack of updates have caused it to fall behind in terms of performance and new React features” [89].
  • Production TanStack Form sightings: OpenAI’s Codex desktop app ships @tanstack/react-form with React 19 [99]; small SaaS teams report it on Next + Zod for highly dynamic forms [98].
  • New entrant to watch, not to bet on: Formisch ⭐ 1.0k, by Fabian Hiller (author of Valibot, co-author of Standard Schema). Signal-based, ~2.5 kB core, six frameworks, and the only library that derives types straight off the schema with no generic and no resolver — which it achieves by binding to Valibot only, rather than accepting any Standard Schema [107] [108]. ⚠ Worth noticing: the Standard-Schema co-author’s own form library does not consume Standard Schema, which tells you something about the ceiling on schema-derived inference through that interface. 1.0.0-rc.0, 2.5k weekly downloads: real, very early [56] ⭐ 1.0k [97] ⭐ 1.0k. Its comparison blog is a competitor’s vendor blog — directionally useful, adversarial by construction [55].
  • Coverage caveat: Reddit blocks automated fetching, so the “practitioner sentiment” above is sourced from Hacker News, GitHub discussions and blogs — not r/reactjs. Weight it accordingly.

Three claims that are repeated in 2026 and are not true

  1. “State of React 2025 says RHF 74%, TanStack Form 21%.” The survey has no form-library question [26] [28].
  2. “RHF is 3× smaller than Formik.” 12.87 kB vs 13.12 kB in July 2026 [29] [32]. The 8.5-vs-15 kB figure is from RHF’s own FAQ, citing 2022 versions [45].
  3. “RHF has no React Compiler or SSR support” (per TanStack’s comparison table [51]). RHF v8 beta’s headline feature is zero-config React Compiler support [5], and the repo pushed on 2026-07-12 [3] ⭐ 44.8k. Conversely, ✗ “RHF is legacy” is also false — 175 commits in the six months to 2026-07-13 [3] ⭐ 44.8k.

Citations · 109 sources

Click the Citations tab to load…