SpikeMe
← Comparisons
Forms

React Hook Form vs Formik

updated on July 14, 2026

React Hook Form vs Formik

React Hook Form and Formik compared on input model (uncontrolled vs controlled), re-renders, bundle size, and maintenance, with real npm data and a verdict by context.

FactReact Hook FormFormik
Current version7.81.02.4.9
Downloads/week (npm)57,978,0084,270,094
LicenseMITApache-2.0
Bundle (gzip)12.8 kB
CriterionReact Hook FormFormik
Modeluncontrolled inputs via refs (register)controlled components, form state in React
Re-rendersminimal, isolates the field that changedre-renders the form on every keystroke by default
Bundle sizevery small, no extra dependencieslarger (around 12.8 kB gzip)
Validationresolvers for Zod or Yup, or native validation via registervalidate prop or validationSchema (Yup)
DX and boilerplateless code: register and handleSubmit are enoughmore verbose: Formik, Field, and ErrorMessage components
Maintenance and activityvery active, huge adoption (around 58M/week)pace has slowed (around 4.3M/week, v2.4.9)
UI library integrationController to wrap third-party controlled componentscontrolled components fit directly into the model

Context

Both solve the same problem (managing state, validation, and submission of React forms), but they start from opposite architectural decisions about where the form state lives. Formik was the default choice for years: each field is a controlled component, the value lives in React state, and the form re-renders on every keystroke. React Hook Form made the inverse bet: inputs stay uncontrolled, registered via refs with register, and the library only re-renders what actually needs it. That difference in model (controlled vs uncontrolled) is the root of nearly everything that separates the two in practice, from performance to boilerplate.

There is also a data point that doesn't fit in the feature table and that weighs heavily on the decision today: the gap in adoption and maintenance. React Hook Form is past 58 million weekly downloads and stays in very active development; Formik sits around 4.3 million, stuck on v2.4.9, with a much slower maintenance pace. This isn't a technical tie broken by taste: React Hook Form has become the modern default of the ecosystem.

When to choose React Hook Form

React Hook Form pays off in practically any new project, and the gain shows up strongest in large forms, where the uncontrolled model avoids re-rendering the whole form on every keystroke:

import { useForm } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod";
import { z } from "zod";

const schema = z.object({ email: z.string().email() });
type FormData = z.infer<typeof schema>;

export function SignupForm() {
  const {
    register,
    handleSubmit,
    formState: { errors },
  } = useForm<FormData>({ resolver: zodResolver(schema) });

  return (
    <form onSubmit={handleSubmit((data) => console.log(data))}>
      <input {...register("email")} />
      {errors.email && <span>{errors.email.message}</span>}
      <button type="submit">Enviar</button>
    </form>
  );
}

register connects the input by ref, without turning it into a controlled component, and handleSubmit only fires after validation passes. Validation comes cheap through a resolver: the same Zod (or Yup) schema you already use on the backend validates the form, without rewriting rules. Boilerplate is minimal (register and handleSubmit cover the common case) and the bundle is tiny, with no extra dependencies. The one thing to watch for is integrating third-party controlled UI components (a library Select, for example): that's where <Controller> comes in, bridging React Hook Form's uncontrolled model and a component that expects value/onChange.

When to choose Formik

Formik makes sense mostly when the cost is maintenance rather than choice: legacy forms already written in it, that work and pass their tests, rarely justify a rewrite just for the migration.

import { Formik, Form, Field, ErrorMessage } from "formik";
import * as Yup from "yup";

const schema = Yup.object({ email: Yup.string().email().required() });

export function SignupForm() {
  return (
    <Formik
      initialValues={{ email: "" }}
      validationSchema={schema}
      onSubmit={(values) => console.log(values)}
    >
      <Form>
        <Field name="email" />
        <ErrorMessage name="email" component="span" />
        <button type="submit">Enviar</button>
      </Form>
    </Formik>
  );
}

The controlled model has a legitimate advantage: since each Field is already controlled, third-party controlled UI components fit with less ceremony, without needing a wrapper like Controller. In exchange, you pay in re-renders (the form re-renders on every keystroke by default) and in verbosity (Formik, Form, Field, and ErrorMessage for what React Hook Form solves with two functions). The point that weighs most isn't in the code: Formik has slowed down. Starting a new project on it today means choosing the piece with less active maintenance and a community that has already moved on.

Verdict

For a new project, the answer is direct: React Hook Form. The uncontrolled model delivers minimal re-renders and a small bundle, boilerplate is lower, resolver-based validation reuses the Zod or Yup schema you already have, and the massive adoption means examples, integrations, and answers for practically any case. The only real friction, integrating third-party controlled components, is solved with Controller, a well-documented pattern.

Formik isn't a wrong choice, it's a dated one. It was the ecosystem default for good reasons and still works well in code that already exists, so migrating a mature, tested Formik form just for the migration rarely pays off. But the gap in maintenance and adoption (around 58M against 4.3M weekly downloads, with Formik stuck on v2.4.9) has made the greenfield decision almost automatic: anyone about to write "I'll use Formik" on a new project should first ask why not React Hook Form.

React Hook Form

Choose React Hook Form if…

Choose React Hook Form for practically every new project: uncontrolled inputs via refs deliver minimal re-renders, a tiny bundle, and less boilerplate, with validation through Zod or Yup resolvers.

Formik

Choose Formik if…

Choose Formik only if you already have working legacy forms written in it that don't justify a rewrite, aware that the package was the historical default but has slowed on maintenance.

The numbers above came from the registry, with source and date. Still, this comparison is generic: the right answer depends on versions, your team and what already exists in your project.

Generate the spike for YOUR stack

Share

XLinkedIn