Event handling with form data in React js

Last updated: July 23, 2023

Handling form data is a fundamental aspect of web development, and React.js provides powerful tools for efficient event handling. In this blog post, we will explore various techniques for event handling with form data in React.js. We will cover multiple examples and provide step-by-step explanations to help you gain a deep understanding of how to effectively work with form data in React.js applications.

Understanding Form Data and Event Handling in React.js

Before diving into the examples, we will provide an overview of form data and event handling in React.js. Forms in React.js are created using JSX, where various form elements are used to collect user input. Event handling involves capturing user interactions, such as typing, selecting options, and clicking buttons, and updating the component state accordingly.

 

1. Handling Controlled Components

Controlled components are form elements whose values are controlled by React.js. We can control the form input values using the component state, and when the state changes, the form elements reflect those changes.

 

Input Elements


import React, { useState } from 'react';
const FormExample = () => {
 const [name, setName] = useState('');
 const handleChange = (event) => {
   setName(event.target.value);
 };
 return (
   <form>
     <input
       type="text"
       value={name}
       onChange={handleChange}
       placeholder="Enter your name"
     />
     <p>Hello, {name}!</p>
   </form>
 );
};
export default FormExample;

In this example, we create an input element and use the `useState` hook to set up the `name` state. The `handleChange` function updates the `name` state with the input value as the user types. The paragraph below the input element dynamically displays a personalized greeting with the name.


Select Elements


import React, { useState } from 'react';
const FormExample = () => {
 const [country, setCountry] = useState('');
 const handleChange = (event) => {
   setCountry(event.target.value);
 };
 return (
   <form>
     <select value={country} onChange={handleChange}>
       <option value="">Select a country</option>
       <option value="USA">USA</option>
       <option value="Canada">Canada</option>
       <option value="UK">UK</option>
     </select>
     <p>Your selected country: {country}</p>
   </form>
 );
};
export default FormExample;


In this example, we create a select element with multiple options. The `country` state is updated based on the selected option, and the selected country is displayed below the select element.

Checkbox and Radio Buttons


import React, { useState } from 'react';
const FormExample = () => {
 const [newsletter, setNewsletter] = useState(false);
 const [gender, setGender] = useState('');
 const handleNewsletterChange = (event) => {
   setNewsletter(event.target.checked);
 };
 const handleGenderChange = (event) => {
   setGender(event.target.value);
 };
 return (
   <form>
     <label>
       <input
         type="checkbox"
         checked={newsletter}
         onChange={handleNewsletterChange}
       />
       Subscribe to Newsletter
     </label>
     <br />
     <label>
       <input
         type="radio"
         value="male"
         checked={gender === 'male'}
         onChange={handleGenderChange}
       />
       Male
     </label>
     <label>
       <input
         type="radio"
         value="female"
         checked={gender === 'female'}
         onChange={handleGenderChange}
       />
       Female
     </label>
     <p>Newsletter: {newsletter ? 'Subscribed' : 'Not Subscribed'}</p>
     <p>Gender: {gender}</p>
   </form>
 );
};
export default FormExample;


In this example, we use controlled components for checkbox and radio button inputs. The `newsletter` state is updated based on the checkbox state, and the `gender` state is updated based on the selected radio button.

 

2. Uncontrolled Components with Refs

Uncontrolled components allow us to handle form data without controlling the input values using state. Instead, we can use refs to capture the form data.

Capturing Form Data with Refs

import React, { useRef } from 'react';
const FormExample = () => {
 const nameRef = useRef();
 const messageRef = useRef();
 const countryRef = useRef();
 const newsletterRef = useRef();
 const genderRef = useRef();
 const handleSubmit = (event) => {
   event.preventDefault();
   const formData = {
     name: nameRef.current.value,
     message: messageRef.current.value,
     country: countryRef.current.value,
     newsletter: newsletterRef.current.checked,
     gender: genderRef.current.value,
   };
   console.log(formData);
 };
 return (
   <form onSubmit={handleSubmit}>
     <input ref={nameRef} type="text" placeholder="Enter your name" />
     <br />
     <textarea ref={messageRef} placeholder="Enter your message" />
     <br />
     <select ref={countryRef}>
       <option value="">Select a country</option>
       <option value="USA">USA</option>
       <option value="Canada">Canada</option>
       <option value="UK">UK</option>
     </select>
     <br />
     <label>
       <input ref={newsletterRef} type="checkbox" />
       Subscribe to Newsletter
     </label>
     <br />
     <label>
       <input type="radio" ref={genderRef} value="
male" name="gender" />
       Male
     </label>
     <label>
       <input type="radio" ref={genderRef} value="female" name="gender" />
       Female
     </label>
     <br />
     <button type="submit">Submit</button>
   </form>
 );
};
export default FormExample;

In this example, we use refs to capture the form data when the form is submitted. The `handleSubmit` function is triggered on form submission, and it retrieves the input values from the refs and logs them to the console.

 

Resetting Form Data

import React, { useRef } from 'react';
const FormExample = () => {
 const nameRef = useRef();
 const messageRef = useRef();
 const countryRef = useRef();
 const newsletterRef = useRef();
 const genderRef = useRef();
 const handleSubmit = (event) => {
   event.preventDefault();
   const formData = {
     name: nameRef.current.value,
     message: messageRef.current.value,
     country: countryRef.current.value,
     newsletter: newsletterRef.current.checked,
     gender: genderRef.current.value,
   };
   console.log(formData);
   // Reset form data
   event.target.reset();
 };
 return (
   <form onSubmit={handleSubmit}>
     {/* ...input elements and labels... */}
     <br />
     <button type="submit">Submit</button>
   </form>
 );
};
export default FormExample;

In this modified example, we added a line of code to reset the form data after form submission. The `event.target.reset()` method clears all the form fields, making it ready for the user to input new data.

 

Form Submission and Handling

Handling form submission is a critical part of form data handling in React.js. We can utilize the `onSubmit` event of the form element to handle form submission.

 

Handling Form Submission with onSubmit


import React, { useState } from 'react';
const FormExample = () => {
 const [name, setName] = useState('');
 const [email, setEmail] = useState('');
 const [submittedData, setSubmittedData] = useState(null);
 const handleNameChange = (event) => {
   setName(event.target.value);
 };
 const handleEmailChange = (event) => {
   setEmail(event.target.value);
 };
 const handleSubmit = (event) => {
   event.preventDefault();
   const formData = {
     name,
     email,
   };
   setSubmittedData(formData);
   // Reset form data
   setName('');
   setEmail('');
 };
 return (
   <div>
     <form onSubmit={handleSubmit}>
       <label>
         Name:
         <input type="text" value={name} onChange={handleNameChange} />
       </label>
       <br />
       <label>
         Email:
         <input type="email" value={email} onChange={handleEmailChange} />
       </label>
       <br />
       <button type="submit">Submit</button>
     </form>
     {submittedData && (
       <div>
         <h2>Submitted Data</h2>
         <p>Name: {submittedData.name}</p>
         <p>Email: {submittedData.email}</p>
       </div>
     )}
   </div>
 );
};
export default FormExample;

In this example, we handle form submission using the `onSubmit` event of the form element. When the form is submitted, the `handleSubmit` function is called. It creates an object `formData` with the `name` and `email` values. The submitted data is stored in the `submittedData` state and displayed below the form.

 

Preventing Default Behavior

import React, { useState } from 'react';
const FormExample = () => {
 const [name, setName] = useState('');
 const handleSubmit = (event) => {
   event.preventDefault();
   alert(`Hello, ${name}!`);
   // Reset form data
   setName('');
 };
 return (
   <form onSubmit={handleSubmit}>
     <input
       type="text"
       value={name}
       onChange={(e) => setName(e.target.value)}
       placeholder="Enter your name"
     />
     <button type="submit">Submit</button>
   </form>
 );
};
export default FormExample;

In this example, we prevent the default behavior of form submission using `event.preventDefault()`. Instead of submitting the form to the server, it displays an alert message with the user's name.

 

Sending Form Data to the Server

Sending form data to the server typically involves making an HTTP POST request with the form data. To send form data to the server, you can use libraries like Axios or the Fetch API.

 

Validation and Error Handling

Validating user input is essential for ensuring data integrity and providing a better user experience. Let's explore how to implement basic validation and display error messages when the form data is not valid.


import React, { useState } from 'react';
const FormExample = () => {
 const [name, setName] = useState('');
 const [email, setEmail] = useState('');
 const [error, setError] = useState('');
 const handleNameChange = (event) => {
   setName(event.target.value);
 };
 const handleEmailChange = (event) => {
   setEmail(event.target.value);
 };
 const handleSubmit = (event) => {
   event.preventDefault();
   if (!name || !email) {
     setError('Please fill in all fields.');
   } else {
     setError('');
     // Perform further actions or submit the form data to the server
   }
 };
 return (
   <div>
     <form onSubmit={handleSubmit}>
       <label>
         Name:
         <input type="text" value={name} onChange={handleNameChange} />
       </label>
       <br />
       <label>
         Email:
         <input type="email" value={email} onChange={handleEmailChange} />
       </label>
       <br />
       <button type="submit">Submit</button>
     </form>
     {error && <p style={{ color: 'red' }}>{error}</p>}
   </div>
 );
};
export default FormExample;

In this example, we perform basic validation by checking if both the `name` and `email` fields are filled before submitting the form. If any of the fields are empty, an error message is displayed below the form. Otherwise, the form is successfully submitted.

 

Handling Multiple Inputs in a Single Handler

import React, { useState } from 'react';
const FormExample = () => {
 const [formData, setFormData] = useState({
   name: '',
   email: '',
   message: '',
 });
 const handleChange = (event) => {
   const { name, value } = event.target;
   setFormData((prevData) => ({
     ...prevData,
     [name]: value,
   }));
 };
 const handleSubmit = (event) => {
   event.preventDefault();
   console.log(formData);
   // Reset form data
   setFormData({
     name: '',
     email: '',
     message: '',
   });
 };
 return (
   <form onSubmit={handleSubmit}>
     <label>
       Name:
       <input
         type="text"
         name="name"
         value={formData.name}
         onChange={handleChange}
       />
     </label>
     <br />
     <label>
       Email:
       <input
         type="email"
         name="email"
         value={formData.email}
         onChange={handleChange}
       />
     </label>
     <br />
     <label>
       Message:
       <textarea
         name="message"
         value={formData.message}
         onChange={handleChange}
       />
     </label>
     <br />
     <button type="submit">Submit</button>
   </form>
 );
};
export default FormExample;

In this example, we manage multiple form inputs in a single state variable `formData`. The `handleChange` function updates the state based on the input name, making it easy to handle changes in multiple input fields with one handler.

 

Working with Complex Form Data

 

Handling Nested Objects and Arrays

 


import React, { useState } from 'react';
const FormExample = () => {
 const [formData, setFormData] = useState({
   name: '',
   address: {
     city: '',
     country: '',
   },
   hobbies: [],
 });
 const handleChange = (event) => {
   const { name, value } = event.target;
   if (name.includes('.')) {
     const [parent, child] = name.split('.');
     setFormData((prevData) => ({
       ...prevData,
       [parent]: {
         ...prevData[parent],
         [child]: value,
       },
     }));
   } else {
     setFormData((prevData) => ({
       ...prevData,
       [name]: value,
     }));
   }
 };
 const handleHobbiesChange = (event, index) => {
   const hobbies = [...formData.hobbies];
   hobbies[index] = event.target.value;
   setFormData((prevData) => ({
     ...prevData,
     hobbies,
   }));
 };
 const handleAddHobby = () => {
   setFormData((prevData) => ({
     ...prevData,
     hobbies: [...prevData.hobbies, ''],
   }));
 };
 const handleSubmit = (event) => {
   event.preventDefault();
   console.log(formData);
   // Reset form data
   setFormData({
     name: '',
     address: {
       city: '',
       country: '',
     },
     hobbies: [],
   });
 };
 return (
   <form onSubmit={handleSubmit}>
     <label>
       Name:
       <input
         type="text"
         name="name"
         value={formData.name}
         onChange={handleChange}
       />
     </label>
     <br />
     <label>
       City:
       <input
         type="text"
         name="address.city"
         value={formData.address.city}
         onChange={handleChange}
       />
     </label>
     <br />
     <label>
       Country:
       <input
         type="text"
         name="address.country"
         value={formData.address.country}
         onChange={handleChange}
       />
     </label>
     <br />
     <label>Hobbies:</label>
     {formData.hobbies.map((hobby, index) => (
       <div key={index}>
         <input
           type="text"
           value={hobby}
           onChange={(e) => handleHobbiesChange(e, index)}
         />
       </div>
     ))}
     <button type="button" onClick={handleAddHobby}>
       Add Hobby
     </button>
     <br />
     <button type="submit">Submit</button>
   </form>
 );
};
export default FormExample;

In this example, we handle complex form data with nested objects and arrays. The `handleChange` function is modified to handle nested objects. Additionally, we can add and remove hobbies dynamically using the `handleAddHobby` and `handleHobbiesChange` functions.

 

Dynamic Form Fields

import React, { useState } from 'react';
const FormExample = () => {
 const [formData, setFormData] = useState({
   name: '',
   email: '',
   social: {},
 });
 const handleChange = (event) => {
   const { name, value } = event.target;
   setFormData((prevData) => ({
     ...prevData,
     [name]: value,
   }));
 };
 const handleSocialChange = (event) => {
   const { name, value } = event.target;
   setFormData((prevData) => ({
     ...prevData,
     social: {
       ...prevData.social,
       [name]: value,
     },
   }));
 };
 const handleSubmit = (event) => {
   event.preventDefault();
   console.log(formData);
   // Reset form data
   setFormData({
     name: '',
     email: '',
     social: {},
   });
 };
 return (
   <form onSubmit={handleSubmit}>
     <label>
       Name:
       <input
         type="text"
         name="name"
         value={formData.name}
         onChange={handleChange}
       />
     </label>
     <br />
     <label>
       Email:
       <input
         type="email"
         name="email"
         value={formData.email}
         onChange={handleChange}
       />
     </label>
     <br />
     <label>Twitter:</label>
     <input
       type="text"
       name="twitter"
       value={formData.social.twitter || ''}
       onChange={handleSocialChange}
     />
     <br />
     <label>LinkedIn:</label>
     <input
       type="text"
       name="linkedin"
       value={formData.social.linkedin || ''}
       onChange={handleSocialChange}
     />
     <br />
     <button type="submit">Submit</button>
   </form>
 );
};
export default FormExample;

In this example, we create dynamic form fields for social media links. The `social` field is an object that can have different social media properties. The `handleSocialChange` function allows users to add and edit social media links dynamically.

 

In this tutorial, we covered various techniques for handling form data in React.js applications. We explored controlled components, uncontrolled components with refs, form submission and handling, validation and error handling, handling multiple inputs with a single handler, and working with complex form data. By mastering these techniques, you can effectively manage and utilize form data, providing a seamless user experience and better interactivity in your React.js applications. Happy coding!

Related post