VOOZH about

URL: https://blog.logrocket.com/build-high-performance-forms-using-react-final-form/

⇱ React Final Form: A library for more performant forms - LogRocket Blog


2021-07-15
1376
#react
Kasra Khosravi
58938
👁 Image

See how LogRocket's Galileo AI surfaces the most severe issues for you

No signup required

Check it out

There are many libraries available for creating and managing forms. In React, forms have always been a bit complex. Form libraries aim to simplify form management without compromising performance.

👁 Build High Performance Forms React Final Form

In this article, we’ll look at React Final Form, a popular library for form management. We’ll cover how React Final Form works, compare it to some competitors, and, finally, test it out with a relevant example. Let’s get started!

🚀 Sign up for The Replay newsletter

The Replay is a weekly newsletter for dev and engineering leaders.

Delivered once a week, it's your curated guide to the most important conversations around frontend dev, emerging AI tools, and the state of modern software.

What is React Final Form?

React Final Form is a lightweight form library written in core JavaScript that acts as a wrapper around Final Form, a form state management library.

React Final Form uses the observer design pattern in which the components subscribe to specific events. Instead of the whole form re-rendering, only the fields that have been subscribed re-render.

Let’s look at some main features of React Final Form.

Minimal bundle size

React Final Form is simple a wrapper around the Final Form library. It has zero dependencies and is written in pure JavaScript, making it framework agnostic. The bundle size of React Final Form is only 3.2kB minified and gzipped.

Simplicity

Due to its simple form state management, React Final Form emphasizes writing code for required functionality over unnecessarily writing code for simple forms. React Final Form’s design is highly modular, making it a perfect choice for many use cases.

High performance

Although re-rendering is not a big deal in small forms, as form size increases, we see a significant lag in performance with each re-render. Due to its subscription-based pattern, React Final Form only re-renders required fields, preventing delays.

Now that we know the basics of React Final Form, let’s take a look at Formik, a similar library, to see how the two compare.

Comparison to Formik

Formik is a library that assists developers in three areas of writing React code: getting values in and out of form state, validation and error messages, and form submission.

Popularity and community

Let’s look at both libraries on npm trends to gage popularity and community size. We see that over the last six months, Formik has obtained a higher number of weekly downloads than React Final Form.

👁 Formik React Final Form Npm Downloads

On GitHub, React Final Form has 6.6K stars, while Formik has 27.7K stars. Formik clearly has a larger online community, however, there are plenty of threads and forums for both libraries, meaning you should be able to receive community support.

As seen in the screenshot below, both libraries are updated frequently:

👁 React Final Form Formik Updates

React Final Form currently has fewer open issues on GitHub than Formik, but this may change in the future if the library grows in popularity.

Size and dependencies

Formik’s bundle size is 13kB, which is larger than React Final Form’s bundle size of 3.2 kB.

Below, we can see the bundle composition for both libraries. React Final Form has fewer dependencies, reducing the chance of the library breaking up when updated.

👁 React Final Form Bundle Composition

👁 Formik Bundle Composition

Setting up React Final Form

Let’s test React Final Form’s functionality by starting our own project. Set up a React project and install the React Final Form library by running the following command:

npm install --save final-form react-final-form

Once the library is installed, import the main components from the library as follows:

import { Form, Field } from 'react-final-form'

Note that in the code snippet above, we import two components, Form and Field. Form is the parent component that takes all the props for the management of our form, and Field wraps the HTML elements to create a standalone Final Form component. The component created by Field has its own state that is managed by the Form tag.

Let’s write the code for a simple input form in React Final Form. Our code contains input fields for firstName and lastName. We also add a submit button:

/* eslint-disable jsx-a11y/accessible-emoji */
import React from 'react'
import { render } from 'react-dom'
import Styles from './Styles'
import { Form, Field } from 'react-final-form'

const sleep = ms => new Promise(resolve => setTimeout(resolve, ms))

const onSubmit = async values => {
 await sleep(300)
 window.alert(JSON.stringify(values, 0, 2))
}

const App = () => (
 <Styles>
 <h1>React Final Form - Simple Example</h1>

 <Form
 onSubmit={onSubmit}
 initialValues={{ firstname: '', lastname :''}}
 render={({ handleSubmit, form, submitting, pristine, values }) => (
 <form onSubmit={handleSubmit}>
 <div>
 <label>First Name</label>
 <Field
 name="firstName"
 component="input"
 type="text"
 placeholder="First Name"
 />
 </div>
 <div>
 <label>Last Name</label>
 <Field
 name="lastName"
 component="input"
 type="text"
 placeholder="Last Name"
 />
 </div>

 <div className="buttons">
 <button type="submit" disabled={submitting || pristine}>
 Submit
 </button>
 <button
 type="button"
 onClick={form.reset}
 disabled={submitting || pristine}
 >
 Reset
 </button>
 </div>
 </form>
 )}
 />
 </Styles>
)

render(<App />, document.getElementById('root'))

Starting the server gives us the following output.

👁 Starting React Final Form Server Output

We are calling two logs, one from the Form and one from the Field. Let’s try entering sam in FirstName to see what happens!


Over 200k developers use LogRocket to create better digital experiences

👁 Image
Learn more →

👁 Call Field Form Logs React Final Form

👁 React Final Form Single Render

Note that Form only rendered once. The Field component shows independent behavior because it renders the same number of times as the number of characters entered. In React, we should always aim for a smaller number of re-renders to avoid delays as our form size grows.

We used a render prop, which gives us access to different props from the Form component. See the final output of our example below:

👁 React Final Form Example Form

Now that we’ve seen how React Final Form works, let’s run the same example using Formik.

Setting up Formik

As before, we’ll set up a simple form with a field for firstName a field for lastName, and a submit button. Let’s call our form Client Profile:

import React from "react";
import ReactDOM from "react-dom";
import { Formik, Form, Field } from "formik";


// Messages
export default function App() {
 return (
 <Formik
 initialValues={{
 firstname: "",
 lastname: "",
 }}
 onSubmit={(values, { setSubmitting }) => {
 setTimeout(() => {
 console.log(JSON.stringify(values, null, 2));
 setSubmitting(false);
 }, 400);
 }}
 >
 {({ errors, touched, isValidating }) => (
 <div className="container">
 <div>
 <h3>Client Profile</h3>
 </div>
 <div>
 <Form>
 {console.log(“Render”)}
 <div>
 <Field
 type="text"
 placeholder="First Name"
 name="firstname"
 />
 </div>
 <div>
 <Field

 type="text"
 placeholder="lastname"
 name="name" 
 />
 </div>
 <button type="submit">Submit</button>
 </Form>
 </div>
 </div>
 )}
 </Formik>
 );
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

On the first render, our form looks like the image below:



👁 Formik First Render Output

We’ve placed a log inside the Form tag that will keep track of the renders. Let’s enter Sam in the input field. We get the following output:

👁 Formik Log Form Tag

Note that the form re-rendered a total of nine times when we entered an input value, as opposed to React Final Form’s single render. Let’s consider these examples in depth.

subscription prop

In React Final Form, the Form component takes the subscription prop, which implements the observer design pattern and causes fewer renders. The subscription prop is similar to the useEffect Hook because it watches the values that have been passed to it and re-renders whenever they are changed.

In the Formik code block above, we do not have passed values inside the prop. Instead, Form is watching {submitting || pristine} for changes.

Validation

React Final Form offers two types of validations: form-level validation and field-level validation. With field-level validation, you can run validation while Field is being changed. In form-level validation, the validation tests are run when the Form is submitted.

Formik has a similar mechanism for validation using a validationSchema. Therefore, both libraries are equal in this regard.

Conclusion

React Final Form’s paradigm for handling forms is different than other libraries. It handles the re-rendering problem of different libraries efficiently by using the observer design pattern.

Not only is React Final Form is smaller in size than Formik, it is also faster. Therefore, if you are aiming to create large and complex forms for your React application without compromising the performance, React Final Form is the best choice.

Get set up with LogRocket's modern React error tracking in minutes:

  1. Visit https://logrocket.com/signup/ to get an app ID
  2. Install LogRocket via npm or script tag. LogRocket.init() must be called client-side, not server-side

    $ npm i --save logrocket 
    
    // Code:
    
    import LogRocket from 'logrocket'; 
    LogRocket.init('app/id');
     
    // Add to your HTML:
    
    <script src="https://cdn.lr-ingest.com/LogRocket.min.js"></script>
    <script>window.LogRocket && window.LogRocket.init('app/id');</script>
     
  3. (Optional) Install plugins for deeper integrations with your stack:
    • Redux middleware
    • NgRx middleware
    • Vuex plugin
Get started now
👁 Image
👁 Image
👁 Image

Stop guessing about your digital experience with LogRocket

Get started for free

Recent posts:

Stop hardcoding LLM SDKs: Dynamic LLM routing with OpenRouter and Next.js

Build dynamic LLM routing in Next.js with OpenRouter, TanStack AI, task classification, model fallbacks, and cost-aware routing.

👁 Image
Chizaram Ken
Jun 16, 2026 ⋅ 13 min read

What is TSRX?: What JSX would look like if it were designed today

TSRX adds first-class control flow, conditional hooks, and scoped styles to React via a TypeScript compiler extension — no new framework required.

👁 Image
Ikeh Akinyemi
Jun 12, 2026 ⋅ 6 min read

How to add authentication to a React Native app with Better Auth

Learn how to build a full React Native auth system using Better Auth and Expo — with email/password login, Google OAuth, session persistence, and protected routes.

👁 Image
Chinwike Maduabuchi
Jun 9, 2026 ⋅ 13 min read

AI dev tool power rankings & comparison [June 2026]

Compare the top AI development tools and models of June 2026. View updated rankings, feature breakdowns, and find the best fit for you.

👁 Image
Chizaram Ken
Jun 8, 2026 ⋅ 11 min read
View all posts

Would you be interested in joining LogRocket's developer community?

Join LogRocket’s Content Advisory Board. You’ll help inform the type of content we create and get access to exclusive meetups, social accreditation, and swag.

Sign up now