Migrating from Formik to React Hook Form 7: A Comprehensive Guide with Examples
As the JavaScript ecosystem continues to evolve, new libraries and frameworks continuously arise, often delivering more effective solutions for developers. One such solution is React Hook Form (RHF), which has emerged as a strong alternative to Formik, particularly with the introduction of its version 7.
This guide aims to provide a detailed, step-by-step process for migrating from Formik to React Hook Form 7, complete with examples. We’ll focus on the main areas of difference between the two form libraries and illustrate how to handle them effectively.
What is React Hook Form?
React Hook Form is a form library for React and React Native that provides a performant, flexible, and developer-friendly API. The library focuses on delivering excellent user experiences by minimising re-renders, leveraging React’s native form API, and providing powerful validation capabilities.
The Migration Process
1. Installation
Firstly, uninstall Formik from your project:
npm uninstall formik
Then, install React Hook Form:
npm install react-hook-form
2. Refactoring the Form Component
Formik uses a Form
component to create forms, while React Hook Form uses the native form element. The first step in migration is changing the Formik Form
component to the native form element and adding an onSubmit
event.
Formik:
import { Formik, Form } from 'formik';
function MyForm() {
return (
<Formik initialValues={{...}}>
<Form>
{/* form fields */}
</Form>
</Formik>
);
}
React Hook Form:
import { useForm } from 'react-hook-form';
function MyForm() {
const { handleSubmit } = useForm();
const onSubmit = (data) => {
// handle submit
}
return (
<form onSubmit={handleSubmit(onSubmit)}>
{/* form fields */}
</form>
);
}
3. Refactoring the Field Component
Formik has a custom Field
component, while React Hook Form uses the native input element, and each field must be registered using the register
function.
Formik:
import { Field } from 'formik';
<Field name="myField" />
React Hook Form:
import { useForm } from 'react-hook-form';
function MyForm() {
const { register } = useForm();
return (
<input {...register('myField')} />
);
}
4. Refactoring Validation
Both libraries provide powerful validation options, but they’re implemented differently. Formik uses a validate
function or Yup for validation, while React Hook Form provides the register
function with validation rules.
Formik with Yup:
import { Formik } from 'formik';
import * as Yup from 'yup';
const validationSchema = Yup.object().shape({
myField: Yup.string().required(),
});
<Formik validationSchema={validationSchema} {...}>
React Hook Form:
import { useForm } from 'react-hook-form';
function MyForm() {
const { register } = useForm();
return (
<input {...register('myField', { required: true })} />
);
}
5. Handling Form Errors
Formik stores errors in an errors
object, while React Hook Form stores them in an errors
object returned from the useForm
hook.
Formik:
import { ErrorMessage, Field } from 'formik';
<Field name="myField" />
<ErrorMessage name="myField" component="div" />
React Hook Form:
import { useForm } from 'react-hook-form';
function MyForm() {
const { register, formState: { errors } } = useForm();
return (
<>
<input {...register('myField', { required: true })} />
{errors.myField && <div>This field is required</div>}
</>
);
}
6. Handling Form State
Formik provides a values
prop to access form state, while React Hook Form provides a watch
function.
Formik:
function MyForm({ values }) {
return (
<div>
{values.myField}
</div>
);
}
React Hook Form:
import { useForm } from 'react-hook-form';
function MyForm() {
const { watch } = useForm();
const myField = watch('myField');
return (
<div>
{myField}
</>
);
}
Detailed Example:
Let’s dive into a complete, practical example of migrating from Formik to React Hook Form.
Here’s a simple login form created with Formik:
import { Formik, Field, Form, ErrorMessage } from 'formik';
import * as Yup from 'yup';
const validationSchema = Yup.object().shape({
email: Yup.string().email('Invalid email').required('Required'),
password: Yup.string().min(8, 'Must be at least 8 characters').required('Required'),
});
export function LoginForm() {
return (
<Formik
initialValues={{ email: '', password: '' }}
validationSchema={validationSchema}
onSubmit={(values) => {
console.log(values);
}}
>
<Form>
<Field type="email" name="email" />
<ErrorMessage name="email" component="div" />
<Field type="password" name="password" />
<ErrorMessage name="password" component="div" />
<button type="submit">Submit</button>
</Form>
</Formik>
);
}
Now, let’s see how to migrate this Formik form to a form using React Hook Form.
import { useForm } from 'react-hook-form';
export function LoginForm() {
const { register, handleSubmit, formState: { errors } } = useForm();
const onSubmit = (data) => {
console.log(data);
}
return (
<form onSubmit={handleSubmit(onSubmit)}>
<input type="email" {...register('email', {
required: 'Required',
pattern: {
value: /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$/i,
message: 'Invalid email',
},
})} />
{errors.email && <div>{errors.email.message}</div>}
<input type="password" {...register('password', {
required: 'Required',
minLength: {
value: 8,
message: 'Must be at least 8 characters',
},
})} />
{errors.password && <div>{errors.password.message}</div>}
<button type="submit">Submit</button>
</form>
);
}
This example covers all the essential aspects of migrating a Formik form to React Hook Form: changing the form and field components, validation rules, error handling, and form submission.
Conclusion
The migration from Formik to React Hook Form involves several crucial steps, each requiring its unique attention to detail. This guide is a comprehensive overview of these steps. While the two libraries have a different approach to form handling, they both provide a robust solution for form management in React.
Remember, it’s essential to test all forms after migration to ensure they behave as expected. Migrating gradually, form by form, can be a safe and controlled strategy. Happy coding!