От халепа... Ця сторінка ще не має українського перекладу, але ми вже над цим працюємо!
От халепа... Ця сторінка ще не має українського перекладу, але ми вже над цим працюємо!
Ihor Belehai
/
Front End Developer
9 min read
Article content:
Data is a vital tool for businesses of all kinds. And the more successful your data collection, the more valuable insights you’ll gain.
Creating effective and clear forms for your clients to fill out contributes to an efficient user experience and furthers your data collection and monetization goals.
Therefore, we’re starting a series of articles about building effective forms with React, Typescript, React Hook Form, Material UI, and Yup.
In this article, we’ll configure the necessary elements and determine the data structure. Then we’ll explain the React Hook Form library and its primary strengths.
If you want to see the final source code, you can check it out here.
You can also play with this demo.
Let’s make a short checklist of what to keep in mind when creating a form to elicit and capture information.
The main takeaways are:
These are only the essential points to consider. Keeping them in mind creates efficient interaction between users and your business, facilitated by the Web.
See also: How to start with animations on Vue.js: a small guide for beginners
To get started, we recommend you bootstrap this project quickly using our NextJS-TailwindCSS-Typescript template. You’re welcome to use and share it with others; hopefully, it helps you with your tasks.
Instead, you could always do a lengthy, boring manual setup, as follows:
1. Create React project:
npx create-react-app form-app
Or if you want to use NextJS:
npx create-next-app form-app
2. Add Typescript to the project.
3. Install dependencies:
npm i react-hook-form
Before starting to code, it’s always important to define the data structure of what you’re building. This ensures consistency and makes your code much more maintainable.
Let’s suppose your customer says they need an intake form for a veterinarian with the following wireframe:
According to the wireframe, the form will have the following structure:
title — required, min 2 characters, max 120
date — date picker, required, min date is today
selected plan — dropdown, one of Premium/Basic, required,
pet information:
name — required, min 2 characters, max 120
breed — required, min 2 characters, max 120
description — optional, min 2 characters, max 500
contact information:
first name — required, min 2 characters, max 120
last name — required, min 2 characters, max 120
phone number — required, correct phone number format
email — optional, correct email format
call me back — checkbox, true/false
Submit
Let’s start with the first bit of code.
Create the file models.ts in the root folder of your project and describe the form with Typescript interfaces.
export interface Appointment { id?: string; title: string; date: string; plan: AppointmentPlan pet: Pet; contact: ContactInfo; } export interface Pet { name: string; breed: string; description?: string; } export interface ContactInfo { firstName: string; lastName: string; phoneNumber: string; email?: string; callMeBack: boolean } export enum AppointmentPlan { Basic = 'Basic', Premium = 'Premium' }
1.Create a file: /components/AppointmentForm.tsx
2. Import some modules.
import { useForm, UseFormReturn, UseFormProps } from 'react-hook-form'; import { Appointment, AppointmentPlan } from '../models';
3. Create the object defaultValues: Appointment to store the initial state of the form.
const defaultValues: Appointment = { title: '', date: new Date().toString(), plan: AppointmentPlan.Basic, contact: { firstName: '', lastName: '', email: '', phoneNumber: '', callMeBack: false, }, pet: { name: '', breed: '' }, };
4. Create a component called AppointmentForm and initialize the React Hook Form.
export const AppointmentForm = () => { // React Hook Form initialization const form: UseFormReturn<Appointment, UseFormProps> = useForm<Appointment>({ defaultValues }); // Submit handler const submitForm = () => {}; return ( <form onSubmit={submitForm}> <h1 className="font-semibold my-4 text-2xl text-center"> Create a new appointment </h1> <button type="submit">Make an appointment!</button> </form> ); };
useForm returns the object of type UseFormReturn, which has a variety of actions that allow controlling the form:
Let’s use some of them now and see what Hook Form is capable of.
5. Create form inputs for each field of the form and connect them to React Hook Form with the register method. As a parameter, specify a form property name corresponding to an input.
<form onSubmit={submitForm}> <h1>Create an appointment</h1> <input {...form.register('title')} type="text" /> <input {...form.register('date')} type="date" /> <select {...form.register('plan')} > <option value={AppointmentPlan.Basic}>Basic</option> <option value={AppointmentPlan.Premium}>Premium</option> </select> <h2>Pet information</h2> <input {...form.register('pet.name')} type="text" /> <input {...form.register('pet.breed')} type="text" /> <textarea {...form.register('pet.description')} type="text" /> <h2>Contact information</h2> <input {...form.register('contact.firstName')} type="text" /> <input {...form.register('contact.lastName')} type="text" /> <input {...form.register('contact.phoneNumber')} type="text" /> <input {...form.register('contact.email')} type="email" /> <label htmlFor="contact.callMeBack"> Call me back to confirm order <input {...form.register('contact.callMeBack')} type="checkbox" id="contact.callMeBack" /> </label> </form>
6.Wrap the submit handler with handleSubmit.
<form onSubmit={form.handleSubmit(submitForm)}>
handleSubmit is a function that performs a form validation and triggers the submit handler only when the validation runs successfully. This function is async, which means that React Hook Form performs asynchronous validation.
7. Now you can access the form value as an argument inside of your submit handler.
const submitForm = (appointment: Appointment) => { // todo: do whatever after submitting };
8. Also, you may style the form and its layout to your taste; in my case, I used the TailwindCSS grid to set the layout. You can just copy-paste the code (we have more exciting topics to cover, so it’s best not to get distracted with these trifles).
import React from 'react'; import { useForm, UseFormProps, UseFormReturn, FormProvider, } from 'react-hook-form'; import { Appointment, AppointmentPlan } from '../models'; const defaultValues: Appointment = { title: '', date: new Date().toString(), plan: AppointmentPlan.Basic, contact: { firstName: '', lastName: '', email: '', phoneNumber: '', callMeBack: false, }, pet: { name: '', breed: '', description: '', }, }; export const AppointmentForm = () => { const form: UseFormReturn<Appointment, UseFormProps> = useForm<Appointment>({ defaultValues }); const submitForm = (form: Appointment) => { // todo: do whatever after submitting }; return ( <form onSubmit={form.handleSubmit(submitForm)}> <h1 className="font-semibold my-4 text-2xl text-center"> Create a new appointment </h1> <section className="grid grid-cols-2 gap-6"> <div className="col-span-2"> <label htmlFor="title">Title*</label> <input {...form.register('title')} type="text" /> </div> <div className="col-span-1"> <label htmlFor="date">Date*</label> <input {...form.register('date')} type="date" id="date" /> </div> <div className="col-span-1"> <label htmlFor="plan">Select plan*</label> <select {...form.register('plan')} id="plan"> <option value={AppointmentPlan.Basic}>Basic</option> <option value={AppointmentPlan.Premium}>Premium</option> </select> </div> </section> <h2 className="font-semibold my-4 text-lg"> Pet information </h2> <section className="grid grid-cols-2 gap-6"> <div className="col-span-1"> <label htmlFor="pet.name">Name*</label> <input {...form.register('pet.name')} type="text" id="pet.name" /> </div> <div className="col-span-1"> <label htmlFor="pet.breed">Breed*</label> <input {...form.register('pet.breed')} type="text" id="pet.breed" /> </div> <div className="col-span-2"> <label htmlFor="pet.description">Description</label> <textarea {...form.register('pet.description')} id="pet.description" /> </div> </section> <h2 className="font-semibold my-4 text-lg"> Contact information </h2> <section className="grid grid-cols-2 gap-6"> <div className="col-span-1"> <label htmlFor="contact.firstName">First name*</label> <input {...form.register('contact.firstName')} type="text" id="contact.firstName" /> </div> <div className="col-span-1"> <label htmlFor="contact.lastName">Last name*</label> <input {...form.register('contact.lastName')} type="text" id="contact.lastName" /> </div> <div className="col-span-1"> <label htmlFor="contact.phoneNumber">Phone number*</label> <input {...form.register('contact.phoneNumber')} type="text" id="contact.phoneNumber" /> </div> <div className="col-span-1"> <label htmlFor="contact.email">Email</label> <input {...form.register('contact.email')} type="email" id="contact.email" /> </div> <div className="col-span-2"> <label htmlFor="contact.callMeBack"> Call me back to confirm order <input {...form.register('contact.callMeBack')} type="checkbox" id="contact.callMeBack" /> </label> </div> </section> <button type="submit">Make an appointment!</button> </form> ); }; export default AppointmentForm;
9. Run the app, fill in the form, and press the Make an appointment button. Take a look at the console and make sure that the form works.
See also: What is design thinking and why is it meant to be your guiding light?
We’ve successfully set up the backbone of our future form and ensured that React Hook Form functions. But take a look at the code: this piece is too big. Let’s split it into several logical parts and discover some additional features of React Hook Form.
We’re going to create three new components, as shown in the illustration below:
AppointmentBaseForm AppointmentPetForm AppointmentContactForm
1. Now, let’s go back to components/AppointmentForm.tsx
2. Here, we see a powerful feature of React Hook Form: useFormContext. Let’s import it:
import { useForm, UseFormProps, UseFormReturn, // importing FormProvider FormProvider, } from 'react-hook-form';
3. Wrap your form with FormProvider by spreading the form as a prop:
<FormProvider {...form}> <form onSubmit={form.handleSubmit(submitForm)}> // ... </form> </FormProvider>
Doing so lets all the nested components access the context of this form, which is an advantage because now, you don’t need to pass it as a prop. This allows you to quickly build as many nested forms as you need.
4. Next, you’ll create subcomponents of the form:
components/AppointmentBaseForm.tsx
5. Import useFormContext and some other modules, as depicted below.
import { useFormContext, UseFormProps, UseFormReturn } from 'react-hook-form'; import { Appointment, AppointmentPlan } from '../models';
6. Create the AppointmentBaseForm component, get it from context, and move the title, date, and plan fields there.
export const AppointmentBaseForm = () => { // getting form context const form: UseFormReturn<Appointment, UseFormProps> = useFormContext(); return ( <section className="grid grid-cols-2 gap-6"> <div className="col-span-2"> <label htmlFor="title">Title*</label> <input {...form.register('title')} type="text" /> </div> <div className="col-span-1"> <label htmlFor="date">Date*</label> <input {...form.register('date')} type="date" id="date" /> </div> <div className="col-span-1"> <label htmlFor="plan">Select plan*</label> <select {...form.register('plan')} id="plan"> <option value={AppointmentPlan.Basic}>Basic</option> <option value={AppointmentPlan.Premium}>Premium</option> </select> </div> </section> ); };
In the example above, we get the object form by calling useFormContext. This is an object with the type UseFormReturn<Appointment and UseFormProps>, just like the object in the parent AppointmentForm component. Therefore, we can now use a register to work with our form inside this component.
7. Do the same with the rest of the components. Create AppointmentPetForm.tsx.
import React from 'react'; import { useFormContext, UseFormProps, UseFormReturn } from 'react-hook-form'; import { Appointment } from '../models'; export const AppointmentPetForm = () =&amp;amp;amp;amp;amp;amp;amp;gt; { const form: UseFormReturn&amp;amp;amp;amp;amp;amp;amp;lt;Appointment, UseFormProps&amp;amp;amp;amp;amp;amp;amp;gt; = useFormContext(); return ( &amp;amp;amp;amp;amp;amp;amp;lt;section&amp;amp;amp;amp;amp;amp;amp;gt; &amp;amp;amp;amp;amp;amp;amp;lt;h2 className=&amp;amp;amp;amp;amp;amp;amp;quot;font-semibold my-4 text-lg&amp;amp;amp;amp;amp;amp;amp;quot;&amp;amp;amp;amp;amp;amp;amp;gt; Pet information &amp;amp;amp;amp;amp;amp;amp;lt;/h2&amp;amp;amp;amp;amp;amp;amp;gt; &amp;amp;amp;amp;amp;amp;amp;lt;div className=&amp;amp;amp;amp;amp;amp;amp;quot;grid grid-cols-2 gap-6&amp;amp;amp;amp;amp;amp;amp;quot;&amp;amp;amp;amp;amp;amp;amp;gt; &amp;amp;amp;amp;amp;amp;amp;lt;div className=&amp;amp;amp;amp;amp;amp;amp;quot;col-span-1&amp;amp;amp;amp;amp;amp;amp;quot;&amp;amp;amp;amp;amp;amp;amp;gt; &amp;amp;amp;amp;amp;amp;amp;lt;label htmlFor=&amp;amp;amp;amp;amp;amp;amp;quot;pet.name&amp;amp;amp;amp;amp;amp;amp;quot;&amp;amp;amp;amp;amp;amp;amp;gt;Name*&amp;amp;amp;amp;amp;amp;amp;lt;/label&amp;amp;amp;amp;amp;amp;amp;gt; &amp;amp;amp;amp;amp;amp;amp;lt;input {...form.register('pet.name')} type=&amp;amp;amp;amp;amp;amp;amp;quot;text&amp;amp;amp;amp;amp;amp;amp;quot; id=&amp;amp;amp;amp;amp;amp;amp;quot;pet.name&amp;amp;amp;amp;amp;amp;amp;quot; /&amp;amp;amp;amp;amp;amp;amp;gt; &amp;amp;amp;amp;amp;amp;amp;lt;/div&amp;amp;amp;amp;amp;amp;amp;gt; &amp;amp;amp;amp;amp;amp;amp;lt;div className=&amp;amp;amp;amp;amp;amp;amp;quot;col-span-1&amp;amp;amp;amp;amp;amp;amp;quot;&amp;amp;amp;amp;amp;amp;amp;gt; &amp;amp;amp;amp;amp;amp;amp;lt;label htmlFor=&amp;amp;amp;amp;amp;amp;amp;quot;pet.breed&amp;amp;amp;amp;amp;amp;amp;quot;&amp;amp;amp;amp;amp;amp;amp;gt;Breed*&amp;amp;amp;amp;amp;amp;amp;lt;/label&amp;amp;amp;amp;amp;amp;amp;gt; &amp;amp;amp;amp;amp;amp;amp;lt;input {...form.register('pet.breed')} type=&amp;amp;amp;amp;amp;amp;amp;quot;text&amp;amp;amp;amp;amp;amp;amp;quot; id=&amp;amp;amp;amp;amp;amp;amp;quot;pet.breed&amp;amp;amp;amp;amp;amp;amp;quot; /&amp;amp;amp;amp;amp;amp;amp;gt; &amp;amp;amp;amp;amp;amp;amp;lt;/div&amp;amp;amp;amp;amp;amp;amp;gt; &amp;amp;amp;amp;amp;amp;amp;lt;div className=&amp;amp;amp;amp;amp;amp;amp;quot;col-span-2&amp;amp;amp;amp;amp;amp;amp;quot;&amp;amp;amp;amp;amp;amp;amp;gt; &amp;amp;amp;amp;amp;amp;amp;lt;label htmlFor=&amp;amp;amp;amp;amp;amp;amp;quot;pet.description&amp;amp;amp;amp;amp;amp;amp;quot;&amp;amp;amp;amp;amp;amp;amp;gt;Description&amp;amp;amp;amp;amp;amp;amp;lt;/label&amp;amp;amp;amp;amp;amp;amp;gt; &amp;amp;amp;amp;amp;amp;amp;lt;input {...form.register('pet.description')} type=&amp;amp;amp;amp;amp;amp;amp;quot;text&amp;amp;amp;amp;amp;amp;amp;quot; id=&amp;amp;amp;amp;amp;amp;amp;quot;pet.description&amp;amp;amp;amp;amp;amp;amp;quot; /&amp;amp;amp;amp;amp;amp;amp;gt; &amp;amp;amp;amp;amp;amp;amp;lt;/div&amp;amp;amp;amp;amp;amp;amp;gt; &amp;amp;amp;amp;amp;amp;amp;lt;/div&amp;amp;amp;amp;amp;amp;amp;gt; &amp;amp;amp;amp;amp;amp;amp;lt;/section&amp;amp;amp;amp;amp;amp;amp;gt; ); };
8. And create AppointmentContactForm.tsx.
import React from 'react' import { useFormContext, UseFormProps, UseFormReturn } from 'react-hook-form'; import { Appointment } from '../models; export const AppointmentContactForm = () =&amp;amp;amp;amp;amp;amp;amp;gt; { const form: UseFormReturn&amp;amp;amp;amp;amp;amp;amp;lt;Appointment, UseFormProps&amp;amp;amp;amp;amp;amp;amp;gt; = useFormContext(); return ( &amp;amp;amp;amp;amp;amp;amp;lt;section&amp;amp;amp;amp;amp;amp;amp;gt; &amp;amp;amp;amp;amp;amp;amp;lt;h2 className=&amp;amp;amp;amp;amp;amp;amp;quot;font-semibold my-4 text-lg&amp;amp;amp;amp;amp;amp;amp;quot;&amp;amp;amp;amp;amp;amp;amp;gt; Contact information &amp;amp;amp;amp;amp;amp;amp;lt;/h2&amp;amp;amp;amp;amp;amp;amp;gt; &amp;amp;amp;amp;amp;amp;amp;lt;div className=&amp;amp;amp;amp;amp;amp;amp;quot;grid grid-cols-2 gap-6&amp;amp;amp;amp;amp;amp;amp;quot;&amp;amp;amp;amp;amp;amp;amp;gt; &amp;amp;amp;amp;amp;amp;amp;lt;div className=&amp;amp;amp;amp;amp;amp;amp;quot;col-span-1&amp;amp;amp;amp;amp;amp;amp;quot;&amp;amp;amp;amp;amp;amp;amp;gt; &amp;amp;amp;amp;amp;amp;amp;lt;label htmlFor=&amp;amp;amp;amp;amp;amp;amp;quot;contact.firstName&amp;amp;amp;amp;amp;amp;amp;quot;&amp;amp;amp;amp;amp;amp;amp;gt;First name*&amp;amp;amp;amp;amp;amp;amp;lt;/label&amp;amp;amp;amp;amp;amp;amp;gt; &amp;amp;amp;amp;amp;amp;amp;lt;input {...form.register('contact.firstName')} type=&amp;amp;amp;amp;amp;amp;amp;quot;text&amp;amp;amp;amp;amp;amp;amp;quot; id=&amp;amp;amp;amp;amp;amp;amp;quot;contact.firstName&amp;amp;amp;amp;amp;amp;amp;quot; /&amp;amp;amp;amp;amp;amp;amp;gt; &amp;amp;amp;amp;amp;amp;amp;lt;/div&amp;amp;amp;amp;amp;amp;amp;gt; &amp;amp;amp;amp;amp;amp;amp;lt;div className=&amp;amp;amp;amp;amp;amp;amp;quot;col-span-1&amp;amp;amp;amp;amp;amp;amp;quot;&amp;amp;amp;amp;amp;amp;amp;gt; &amp;amp;amp;amp;amp;amp;amp;lt;label htmlFor=&amp;amp;amp;amp;amp;amp;amp;quot;contact.lastName&amp;amp;amp;amp;amp;amp;amp;quot;&amp;amp;amp;amp;amp;amp;amp;gt;Last name*&amp;amp;amp;amp;amp;amp;amp;lt;/label&amp;amp;amp;amp;amp;amp;amp;gt; &amp;amp;amp;amp;amp;amp;amp;lt;input {...form.register('contact.lastName')} type=&amp;amp;amp;amp;amp;amp;amp;quot;text&amp;amp;amp;amp;amp;amp;amp;quot; id=&amp;amp;amp;amp;amp;amp;amp;quot;contact.lastName&amp;amp;amp;amp;amp;amp;amp;quot; /&amp;amp;amp;amp;amp;amp;amp;gt; &amp;amp;amp;amp;amp;amp;amp;lt;/div&amp;amp;amp;amp;amp;amp;amp;gt; &amp;amp;amp;amp;amp;amp;amp;lt;div className=&amp;amp;amp;amp;amp;amp;amp;quot;col-span-1&amp;amp;amp;amp;amp;amp;amp;quot;&amp;amp;amp;amp;amp;amp;amp;gt; &amp;amp;amp;amp;amp;amp;amp;lt;label htmlFor=&amp;amp;amp;amp;amp;amp;amp;quot;contact.phoneNumber&amp;amp;amp;amp;amp;amp;amp;quot;&amp;amp;amp;amp;amp;amp;amp;gt;Phone number*&amp;amp;amp;amp;amp;amp;amp;lt;/label&amp;amp;amp;amp;amp;amp;amp;gt; &amp;amp;amp;amp;amp;amp;amp;lt;input {...form.register('contact.phoneNumber')} type=&amp;amp;amp;amp;amp;amp;amp;quot;text&amp;amp;amp;amp;amp;amp;amp;quot; id=&amp;amp;amp;amp;amp;amp;amp;quot;contact.phoneNumber&amp;amp;amp;amp;amp;amp;amp;quot; /&amp;amp;amp;amp;amp;amp;amp;gt; &amp;amp;amp;amp;amp;amp;amp;lt;/div&amp;amp;amp;amp;amp;amp;amp;gt; &amp;amp;amp;amp;amp;amp;amp;lt;div className=&amp;amp;amp;amp;amp;amp;amp;quot;col-span-1&amp;amp;amp;amp;amp;amp;amp;quot;&amp;amp;amp;amp;amp;amp;amp;gt; &amp;amp;amp;amp;amp;amp;amp;lt;label htmlFor=&amp;amp;amp;amp;amp;amp;amp;quot;contact.email&amp;amp;amp;amp;amp;amp;amp;quot;&amp;amp;amp;amp;amp;amp;amp;gt;Email&amp;amp;amp;amp;amp;amp;amp;lt;/label&amp;amp;amp;amp;amp;amp;amp;gt; &amp;amp;amp;amp;amp;amp;amp;lt;input {...form.register('contact.email')} type=&amp;amp;amp;amp;amp;amp;amp;quot;email&amp;amp;amp;amp;amp;amp;amp;quot; id=&amp;amp;amp;amp;amp;amp;amp;quot;contact.email&amp;amp;amp;amp;amp;amp;amp;quot; /&amp;amp;amp;amp;amp;amp;amp;gt; &amp;amp;amp;amp;amp;amp;amp;lt;/div&amp;amp;amp;amp;amp;amp;amp;gt; &amp;amp;amp;amp;amp;amp;amp;lt;div className=&amp;amp;amp;amp;amp;amp;amp;quot;col-span-2&amp;amp;amp;amp;amp;amp;amp;quot;&amp;amp;amp;amp;amp;amp;amp;gt; &amp;amp;amp;amp;amp;amp;amp;lt;label htmlFor=&amp;amp;amp;amp;amp;amp;amp;quot;contact.callMeBack&amp;amp;amp;amp;amp;amp;amp;quot;&amp;amp;amp;amp;amp;amp;amp;gt; Call me back to confirm order &amp;amp;amp;amp;amp;amp;amp;lt;input {...form.register('contact.callMeBack')} type=&amp;amp;amp;amp;amp;amp;amp;quot;checkbox&amp;amp;amp;amp;amp;amp;amp;quot; id=&amp;amp;amp;amp;amp;amp;amp;quot;contact.callMeBack&amp;amp;amp;amp;amp;amp;amp;quot; /&amp;amp;amp;amp;amp;amp;amp;gt; &amp;amp;amp;amp;amp;amp;amp;lt;/label&amp;amp;amp;amp;amp;amp;amp;gt; &amp;amp;amp;amp;amp;amp;amp;lt;/div&amp;amp;amp;amp;amp;amp;amp;gt; &amp;amp;amp;amp;amp;amp;amp;lt;/div&amp;amp;amp;amp;amp;amp;amp;gt; &amp;amp;amp;amp;amp;amp;amp;lt;/section&amp;amp;amp;amp;amp;amp;amp;gt; ); };
9. Import these newly-created components into AppointmentForm.tsx and apply them. In the end, our form looks clearer and more readable.
import React from 'react' import { useForm, UseFormProps, UseFormReturn, FormProvider, } from 'react-hook-form'; import { Appointment, AppointmentPlan } from '../models'; import { AppointmentBaseForm } from './AppointmentBaseForm'; import { AppointmentPetForm } from './AppointmentPetForm'; import { AppointmentContactForm } from './AppointmentContactForm'; const defaultValues: Appointment = { title: '', date: new Date().toString(), plan: AppointmentPlan.Basic, contact: { firstName: '', lastName: '', email: '', phoneNumber: '', callMeBack: false, }, pet: { name: '', breed: '', description: '', }, }; export const AppointmentForm = () =&amp;amp;amp;amp;amp;amp;amp;gt; { const form: UseFormReturn&amp;amp;amp;amp;amp;amp;amp;lt;Appointment, UseFormProps&amp;amp;amp;amp;amp;amp;amp;gt; = useForm&amp;amp;amp;amp;amp;amp;amp;lt;Appointment&amp;amp;amp;amp;amp;amp;amp;gt;({ defaultValues, }); const submitForm = (form: Appointment) =&amp;amp;amp;amp;amp;amp;amp;gt; { // todo: do whatever after submitting }; return ( &amp;amp;amp;amp;amp;amp;amp;lt;FormProvider {...form}&amp;amp;amp;amp;amp;amp;amp;gt; &amp;amp;amp;amp;amp;amp;amp;lt;form onSubmit={form.handleSubmit(submitForm)}&amp;amp;amp;amp;amp;amp;amp;gt; &amp;amp;amp;amp;amp;amp;amp;lt;h1 className=&amp;amp;amp;amp;amp;amp;amp;quot;font-semibold my-4 text-2xl text-center&amp;amp;amp;amp;amp;amp;amp;quot;&amp;amp;amp;amp;amp;amp;amp;gt; Create a new appointment &amp;amp;amp;amp;amp;amp;amp;lt;/h1&amp;amp;amp;amp;amp;amp;amp;gt; &amp;amp;amp;amp;amp;amp;amp;lt;AppointmentBaseForm /&amp;amp;amp;amp;amp;amp;amp;gt; &amp;amp;amp;amp;amp;amp;amp;lt;AppointmentPetForm /&amp;amp;amp;amp;amp;amp;amp;gt; &amp;amp;amp;amp;amp;amp;amp;lt;AppointmentContactForm /&amp;amp;amp;amp;amp;amp;amp;gt; &amp;amp;amp;amp;amp;amp;amp;lt;button type=&amp;amp;amp;amp;amp;amp;amp;quot;submit&amp;amp;amp;amp;amp;amp;amp;quot;&amp;amp;amp;amp;amp;amp;amp;gt;Make an appointment!&amp;amp;amp;amp;amp;amp;amp;lt;/button&amp;amp;amp;amp;amp;amp;amp;gt; &amp;amp;amp;amp;amp;amp;amp;lt;/form&amp;amp;amp;amp;amp;amp;amp;gt; &amp;amp;amp;amp;amp;amp;amp;lt;/FormProvider&amp;amp;amp;amp;amp;amp;amp;gt; ); };
Let’s make sure that the form works. I’ll show you another impressive tool from React Hook Form: Devtools. Yes, DevTools for managing forms makes debugging very easy. Let’s see how it works.
1.Install dependency:
npm i @hookform/devtools
2. Import it inside AppointmentForm.tsx.
import { DevTool } from &amp;amp;amp;amp;amp;amp;amp;quot;@hookform/devtools&amp;amp;amp;amp;amp;amp;amp;quot;;
3. Apply it.
&amp;amp;amp;amp;amp;amp;amp;lt;&amp;amp;amp;amp;amp;amp;amp;gt; &amp;amp;amp;amp;amp;amp;amp;lt;FormProvider {...form}&amp;amp;amp;amp;amp;amp;amp;gt; // ... &amp;amp;amp;amp;amp;amp;amp;lt;FormProvider /&amp;amp;amp;amp;amp;amp;amp;gt; &amp;amp;amp;amp;amp;amp;amp;lt;DevTool control={form.control} /&amp;amp;amp;amp;amp;amp;amp;gt; &amp;amp;amp;amp;amp;amp;amp;lt;&amp;amp;amp;amp;amp;amp;amp;gt;
4. If you go back to your browser, you should see that the following panel has appeared on the right side of the screen:
Press [+] EXPAND to see detailed information about each of your fields. Try to input something into the form to see how it changes and see the magic work!
We’ll go back to this tool in our next post to see how it works for other tasks.
In this post, you dipped your toe into form creation. We used examples to show you how to develop a basic appointment form using React Hook Form.
You saw how valuable React Hook is, as went through the entire process of developing a form from the beginning, including defining the data structure, creating the form, refactoring, and debugging. I hope you enjoyed the journey.
In the following article, I’ll implement form validation with Yup.
Dmytro Ruban
/
Android Developer
— 4 min read