final-form vs formik vs react-hook-form vs redux-form
React Form State Management Libraries
final-formformikreact-hook-formredux-formSimilar Packages:

React Form State Management Libraries

final-form, formik, react-hook-form, and redux-form are all libraries designed to manage form state, validation, and submission in React applications. They abstract away the boilerplate of tracking input values, handling errors, and managing submission logic, but they differ significantly in their underlying architecture, performance characteristics, and integration patterns with React.

Npm Package Weekly Downloads Trend

3 Years

Github Stars Ranking

Stat Detail

Package
Downloads
Stars
Size
Issues
Publish
License
final-form03,045382 kB9710 months agoMIT
formik034,385585 kB8355 months agoApache-2.0
react-hook-form044,6321.28 MB1336 days agoMIT
redux-form012,5151.45 MB4973 years agoMIT

React Form Libraries Compared: final-form, Formik, react-hook-form, and redux-form

Managing forms in React involves tracking values, handling validation, displaying errors, and managing submission — all while avoiding unnecessary re-renders. The four libraries under comparison take different approaches to this problem. Let’s examine how they handle core concerns like state management, validation, and performance.

🧠 Core Architecture: Where Is Form State Kept?

final-form keeps state outside React, in a standalone store. Components subscribe only to the fields they care about, minimizing re-renders.

// final-form: Create form outside component
import { createForm } from 'final-form';

const form = createForm({
  onSubmit: values => console.log(values)
});

// In component
const { blur, change, focus } = form;
const state = form.getState();

formik stores state inside React context. The entire form re-renders on any field change unless you memoize or split components.

// formik: Form state lives in React context
import { Formik, Field, Form } from 'formik';

<Formik
  initialValues={{ email: '' }}
  onSubmit={values => console.log(values)}
>
  <Form>
    <Field name="email" />
  </Form>
</Formik>

react-hook-form avoids React state for inputs by using uncontrolled components and reading values directly from the DOM via refs.

// react-hook-form: Leverages uncontrolled inputs
import { useForm } from 'react-hook-form';

function MyForm() {
  const { register, handleSubmit } = useForm();
  return (
    <form onSubmit={handleSubmit(console.log)}>
      <input {...register('email')} />
    </form>
  );
}

redux-form (deprecated) stores all form state in the global Redux store, causing frequent re-renders and tight coupling to Redux.

// redux-form: Form state in Redux store (DO NOT USE)
import { reduxForm, Field } from 'redux-form';

const MyForm = () => <Field name="email" component="input" />;
export default reduxForm({ form: 'myForm' })(MyForm);

⚠️ Important: redux-form is officially deprecated. The npm page states: "This library is no longer maintained. Please use Final Form or React Hook Form instead."

✅ Validation: Sync, Async, and Conditional Logic

All libraries support synchronous and asynchronous validation, but their APIs differ.

final-form accepts a validate function that returns an error object. Async validation requires manual handling via onSubmit or custom logic.

const form = createForm({
  validate: values => {
    const errors = {};
    if (!values.email) errors.email = 'Required';
    return errors;
  }
});

formik supports both sync and async validation via validate or validationSchema (with Yup).

<Formik
  validate={values => {
    const errors = {};
    if (!values.email) errors.email = 'Required';
    return errors;
  }}
>
  {/* ... */}
</Formik>

react-hook-form offers multiple validation strategies: built-in HTML5 validation, schema-based (Zod, Yup), or custom functions via register.

const { register } = useForm();
<input {...register('email', { required: 'Email is required' })} />;

redux-form used validate prop similarly to Formik, but tied validation results to Redux state.

// redux-form (deprecated)
const validate = values => {
  const errors = {};
  if (!values.email) errors.email = 'Required';
  return errors;
};

export default reduxForm({ form: 'myForm', validate })(MyForm);

📉 Performance: Re-renders and Bundle Impact

final-form excels at performance by allowing components to subscribe only to specific fields. Only subscribed fields trigger re-renders.

// Subscribe only to 'email' changes
const unsubscribe = form.subscribe(
  state => console.log(state.values.email),
  { values: true }
);

formik causes the entire form subtree to re-render on any field change unless you split the form into smaller components or use useField with memoization.

// Without optimization, entire form re-renders
const MyInput = ({ name }) => {
  const [field] = useField(name);
  return <input {...field} />;
};

react-hook-form avoids re-renders entirely for input changes because it doesn’t track values in React state. Only explicit state updates (e.g., errors) cause re-renders.

// Input changes don't trigger re-renders
const { register, formState } = useForm();
// formState.errors changes → re-render; input typing → no re-render

redux-form caused excessive re-renders because every keystroke updated the global Redux store, triggering connected components to update.

🧩 Integration with React: Hooks vs Render Props vs HOCs

final-form is framework-agnostic. You must build your own React integration using hooks or context.

// Custom hook for final-form
function useField(form, name) {
  const [state, setState] = useState(form.getState());
  useEffect(() => {
    return form.subscribe(setState, { values: true, errors: true });
  }, [form, name]);
  return state;
}

formik provides both render props (<Formik>) and hooks (useFormik). The hook version is now preferred.

const formik = useFormik({
  initialValues: { email: '' },
  onSubmit: console.log
});

react-hook-form is built entirely around hooks, aligning with modern React patterns.

const { register, handleSubmit, formState } = useForm();

redux-form relied heavily on higher-order components (HOCs) and Redux connect patterns, which feel outdated in today’s React ecosystem.

🔄 Handling Dynamic Fields

Adding/removing fields dynamically is common in complex forms.

final-form provides mutators for array operations (e.g., push, remove).

import { createForm } from 'final-form';
import { arrayMutators } from 'final-form-arrays';

const form = createForm({ mutators: { ...arrayMutators } });
form.mutators.push('emails', '');

formik includes push, remove, and other array helpers via FieldArray.

<FieldArray name="emails">
  {({ push, remove, form }) => (
    <div>
      {form.values.emails.map((_, i) => (
        <Field name={`emails[${i}]`} />
      ))}
      <button onClick={() => push('')}>Add</button>
    </div>
  )}
</FieldArray>

react-hook-form uses useFieldArray for dynamic lists, which manages refs and state efficiently.

const { fields, append, remove } = useFieldArray({
  name: 'emails'
});

return (
  <div>
    {fields.map((field, i) => (
      <input key={field.id} {...register(`emails.${i}`)} />
    ))}
    <button onClick={() => append('')}>Add</button>
  </div>
);

redux-form supported dynamic fields via Fields and array actions, but required dispatching Redux actions.

📦 Summary Table

Featurefinal-formformikreact-hook-formredux-form
State LocationExternal storeReact contextDOM refs + minimal stateRedux store
Re-render StrategyField subscriptionsFull form re-renderMinimal (uncontrolled)Global Redux updates
Primary APIImperative + subscriptionsHooks / render propsHooksHOCs + Redux actions
Dynamic FieldsMutatorsFieldArrayuseFieldArrayRedux array actions
Maintenance StatusActively maintainedActively maintainedActively maintainedDeprecated

💡 When to Use Which

  • For maximum performance in large forms: react-hook-form or final-form.
  • For quick setup with moderate complexity: formik.
  • For non-React projects or custom renderers: final-form.
  • For new projects: Never redux-form — it’s deprecated.

Choose based on your team’s familiarity, performance needs, and how much control you want over the rendering layer. All three active libraries are solid choices — just match the tool to your constraints.

How to Choose: final-form vs formik vs react-hook-form vs redux-form

  • final-form:

    Choose final-form if you need a framework-agnostic, subscription-based form state manager that minimizes re-renders through fine-grained field subscriptions. It’s ideal when you want full control over rendering and performance optimization without tying your form logic to React’s component lifecycle. However, be prepared to write more integration code since it doesn’t provide React-specific helpers out of the box.

  • formik:

    Choose formik if you prefer a higher-level, component-driven API that wraps your form in a context provider and uses render props or hooks to expose form state and helpers. It’s well-suited for teams that value convention over configuration and don’t have extreme performance requirements. Its declarative validation and built-in support for nested objects make it approachable for medium-complexity forms.

  • react-hook-form:

    Choose react-hook-form if you prioritize performance and minimal re-renders by leveraging uncontrolled components and native HTML form validation. It’s especially effective for large or dynamic forms where every re-render matters. Its hook-based API integrates cleanly with modern React patterns and reduces boilerplate by avoiding unnecessary state synchronization between React and the DOM.

  • redux-form:

    Do not choose redux-form for new projects. It is officially deprecated and no longer maintained, as stated on its npm page and GitHub repository. While it was once popular for deeply integrating form state into Redux stores, its tight coupling to Redux, high re-render overhead, and maintenance burden make it unsuitable for modern applications. Migrate existing implementations to alternatives like react-hook-form or formik.

README for final-form

You build great forms, but do you know HOW users use your forms? Find out with Form Nerd! Professional analytics from the creator of Final Form.


💰 Hey there! Do you fancy yourself a javascript expert? Take this quiz and get offers from top tech companies! 💰


🏁 Final Form

Final Form

Backers on Open Collective Sponsors on Open Collective NPM Version NPM Downloads Build Status codecov.io styled with prettier

Zero dependencies

✅ Framework agnostic

✅ Opt-in subscriptions - only update on the state you need!

✅ 💥 5.1k gzipped 💥


Final Form is sponsored by Sencha.

Comprehensive JS framework and UI components for building enterprise-grade web apps.


💬 Give Feedback on Final Form 💬

In the interest of making 🏁 Final Form the best library it can be, we'd love your thoughts and feedback.

Take a quick survey.


Get Started

Philosophy

Examples

API

Companion Libraries

Who's using Final Form?