Until now, our primary focus has been on presentational components, which don't require extensive user interactions. Let's now pivot toward components dedicated to gathering user input and transmitting it for system processing or storage. These components, known as Forms, will be our primary focus in this lesson. We'll delve into React's native form handling techniques, and see how libraries like Formik and Yup can manage forms more effectively.
Key facets of a form
Form handling typically entails these key units:
- Input fields: Input fields serve as the entry points for users to provide information. These fields come in various types such as text inputs, checkboxes, radio buttons, dropdowns, and more, each tailored to capture specific types of data.
- State management: State management ensures that as users interact with the form, the application captures and manages these changes in real-time. This dynamic handling of data lets users see immediate updates as they fill out the form.
- Validation: Validation ensures the accuracy and completeness of the entered data. It encompasses verifying mandatory fields, validating correct formats like emails or dates, and applying constraints or rules to ensure data integrity. Validation often comes with error messages to help users correct any input discrepancies.
- Submission handling: Upon completion, the submission handling process manages the processing of form data. This could involve sending data to servers for further processing, triggering specific actions based on the user's input, or storing the information within the application's database.
Let us understand these aspects in more detail using an example. We will build a basic contact form that accepts name, email, and message from users, with the aforementioned points in mind. Let's start by defining the input fields. We will use form
, input
and textarea
elements to create the form.
Now, let's associate each input field with a key in the state object variable formData
. This object will be updated using the handleChange
function whenever the user inputs data into the fields. The value
attribute of each input field element will be bound to its respective state in the formData
state object. This ensures that the input fields reflect the current state and any changes made by the user are captured.
Our next task is to add validations. At BigBinary, we prefer eager validation since it provides immediate feedback to users as they interact with the form.
We will validate the form fields using the validateField
function whenever the user inputs data into the fields or navigates away from them. It will check if the required fields are empty and if the email
field follows a valid format using a simple regex check. When validation fails for any field, an error message will be stored in the errors
state object corresponding to that field. Error messages will be displayed against each input field if there are validation errors. Additionally, we'll include noValidate
in the form
element to bypass default HTML form validations during submission.
Finally, we'll define the handleSubmit
function to handle form submission. This function will be invoked when the form is submitted. To avoid the default form behavior, which reloads the page, we'll use e.preventDefault()
. Then, we will call validateField
on all form fields to validate them upon submission. If the form is valid, the logic for form submission is executed.
Limitations of native form handling in React
Using only built-in React features to handle forms, as we did in the ContactForm
example, can lead to a lot of repetitive code and complexity:
-
Complex State Management: Manually managing form state necessitates creating and updating state variables for each form field, resulting in verbosity and potential synchronization issues. For instance, in the ContactForm
, tracking changes for name
, email
, and message
led to verbose code.
-
Validation Logic: Implementing validation without external libraries involves crafting custom validations for individual fields, managing error messages, and manually checking input values. In the ContactForm
, we added manual validation in the validateField
function to ensure non-empty names, valid email formats, and non-blank messages.
-
Form Submission Handling: Manual form handling can blur the separation between form validation and submission processes, requiring explicit validation before submission. In the ContactForm
, calling the validateField
function on each of the form fields within the handleSubmit
event handler exemplifies this intertwined nature.
-
Error Handling and Display: Displaying validation errors alongside form fields involves additional logic for conditional rendering. In the ContactForm
, managing error messages for each field using the errors
state and conditional rendering added complexity to the codebase.
These limitations highlight the need for libraries to encapsulate the boilerplate code. There are several libraries that make form management easier in React. Two standout examples are Formik for handling forms and Yup for validation. In the next section, we'll see how these tools make form handling more efficient.
Form handling with Formik and Yup
Formik and Yup streamline the form-building process by cutting down on boilerplate code and substantially reducing code verbosity. Here's an overview of how they accomplish this:
-
Formik centralizes form state management, reducing boilerplate code by automatically handling form values, errors, touched fields, and form submission.
-
Yup schema allows for declarative and concise form validation, simplifying the process of defining and executing validation rules. Formik provides various validation strategies, allowing developers to choose how and when validation should occur.
-
Formik decouples form submission logic from validation. Upon successful validation, Formik's onSubmit
handler is solely responsible for executing form submission logic.
-
Formik offers built-in error handling mechanisms that seamlessly integrate with the form fields, providing a more user-friendly way to display validation errors.
In the upcoming lessons, we'll explore the specifics of managing forms using Formik and implementing validation with Yup.