Embracing React Hook Form
As a developer, I've always had a penchant for minimalism. I preferred crafting things from scratch, avoiding the potential bloat of unnecessary packages, but mainly because it was the industry standard to minimize packages and in that sense, I am a bit of sheep. Handling forms was something I stayed adamant on. Why rely on external packages when I could manage forms manually, I thought? Why use someone else's code for something so simple? However, life often has a way of challenging our perspectives, and in this case, React Hook Form proved to be the irresistible exception.
The DIY Approach
For the longest time, I was stubbornly committed to my DIY approach when it came to forms in React. I believed that by manually handling form validation, state management, and submission logic, I had full control and could optimize for my specific use case and importantly use one less package. This meant writing extensive code to handle field validation, maintaining form state, and managing submission events. Take the simple example below.
// Manually handling form state and validation const [name, setName] = useState(''); const [email, setEmail] = useState(''); const [message, setMessage] = useState(''); const handleSubmit = (e) => { e.preventDefault(); // Manual validation checks and submission logic }; <form onSubmit={handleSubmit}> <input type="text" value={name} onChange={(e) => setName(e.target.value)} /> {/* Other fields */} <button type="submit">Submit</button> </form>
Here, we set a measly three states. That's not much to handle, is it? You'd be right. When forms are just a few input fields and the UI is simple, then it's justifiable to manually handle the logic. However, when you begin to consider error states, onChange, onBlur, multi-step forms, validation, loading spinners and more, that's when the code can become unmaintainable. Sure, there are clean-ups and optimizations you can make, but do they go far enough?
// old version const [name, setName] = useState(''); const [email, setEmail] = useState(''); const [message, setMessage] = useState(''); // new version const initialValues = { name: "", email: "", message: "" } const [formValues, setFormValues] = useState(initialValues);
The Temptation of React Hook Form
The turning point arrived when I simply decided one day that this time I'll try out React Hook Form. I don't know why I abandoned my stubbornness that day, but I did. As I dug deeper, I realized that it offered significant benefits that aligned perfectly with all the headaches from tiresome form coding in the past.
- Simplicity and Performance
React Hook Form drastically simplified my form handling code. With minimal setup, I could achieve complex form validation and state management effortlessly.
// Using React Hook Form import { useForm } from 'react-hook-form'; const { register, handleSubmit, reset, formState: { errors, isSubmitting }, } = useForm<ContactFormType>({ resolver: zodResolver(contactFormValidator), defaultValues: { name: "", email: "" }, const onSubmit = (data) => { // Submission logic with validated data }; // Form JSX <form onSubmit={handleSubmit(onSubmit)}> <input {...register("name") /> {errors.name && <span>This field is required</span>} <input {...register("email") /> {errors.email && <span>This field is required</span>} <button type="submit">Submit</button> </form>
The above is almost beautiful. It's so clean and pure. All we have to do is destructure register, handleSubmit, reset and formState from the useForm() hook.
- register - Register allows us to register an input to the form. It providers us with onChange, onBlur, ref and name. To get that all we need to write is {...register("name")}.
- handleSubmit - This function will receive the form data if validation is successful. More on that later.
- reset - Simply resets the form fields when invoked.
- formState - This is an object which contains many properties all related to the form state. Most used for me are 'errors' and 'isSubmitting'. With these two I can handle loading spinners and easily conditionally display errors.
- Validation
Validation is another important and burdensome task when done manually. In the above example, I use zod and zodResolver to feed the form submission my validator. Now, on the client side, React Hook Form will automatically handle the validation and conditionally display them using the errors object.
- Better Performance
React Hook Form optimized performance by minimizing unnecessary re-renders. The controlled components automatically updated only the necessary parts of the DOM when values changed.
The Decision to Switch
As I compared the lines of code and the development effort required by both approaches, the allure of React Hook Form became undeniable. The convenience of the package didn't compromise my minimalist principles; instead, it amplified my efficiency as a developer.
Embracing React Hook Form wasn't a betrayal of my DIY ethos; it was an evolution. I have long since embraced React Hook Form and there is no going back.
Conclusion
The journey from staunchly handling forms manually to adopting React Hook Form was a transformative one. Sometimes, letting go of the reins leads to greater mastery. React Hook Form proved that relinquishing a bit of control can, paradoxically, give us more.
npm install react-hook-form