Forms are a fundamental part of web applications, allowing users to input data and interact with your application. In React, handling forms can be done using controlled components or uncontrolled components. This tutorial will cover both methods, along with best practices and real-world examples.
Controlled components in React are form elements whose values are controlled by the state of the component. The value of the input element is set by the value attribute, and any changes to the input are handled through event handlers like onChange.
Let's start with a simple example of a controlled input field.
import React, { useState } from 'react';
function NameForm() {
const [name, setName] = useState('');
const handleChange = (event) => {
setName(event.target.value);
};
const handleSubmit = (event) => {
event.preventDefault();
alert('A name was submitted: ' + name);
};
return (
<form onSubmit={handleSubmit}>
<label>
Name:
<input type="text" value={name} onChange={handleChange} />
</label>
<input type="submit" value="Submit" />
</form>
);
}
export default NameForm;
useState hook to create a state variable name and a function setName to update it.handleChange function updates the state whenever the input changes, making the component "controlled".handleSubmit function prevents the default form submission behavior and alerts the user with the submitted name.Uncontrolled components store their own state in the DOM. To access the value, you use a ref to get the value from the DOM element.
Here's how you can implement an uncontrolled component for a form.
import React, { useRef } from 'react';
function NameForm() {
const inputRef = useRef(null);
const handleSubmit = (event) => {
event.preventDefault();
alert('A name was submitted: ' + inputRef.current.value);
};
return (
<form onSubmit={handleSubmit}>
<label>
Name:
<input type="text" ref={inputRef} />
</label>
<input type="submit" value="Submit" />
</form>
);
}
export default NameForm;
useRef hook to create a reference to the input element.handleSubmit function, we access the input's value using inputRef.current.value.For forms with multiple inputs, you can use a single state object to manage all the input values.
import React, { useState } from 'react';
function Reservation() {
const [formData, setFormData] = useState({
firstName: '',
lastName: '',
isGoing: true,
numberOfGuests: 2,
});
const handleChange = (event) => {
const { name, value, type, checked } = event.target;
setFormData({
...formData,
[name]: type === 'checkbox' ? checked : value,
});
};
const handleSubmit = (event) => {
event.preventDefault();
alert('A reservation was submitted for: ' + formData.firstName);
};
return (
<form onSubmit={handleSubmit}>
<label>
First Name:
<input
name="firstName"
type="text"
value={formData.firstName}
onChange={handleChange}
/>
</label>
<br />
<label>
Last Name:
<input
name="lastName"
type="text"
value={formData.lastName}
onChange={handleChange}
/>
</label>
<br />
<label>
Is going:
<input
name="isGoing"
type="checkbox"
checked={formData.isGoing}
onChange={handleChange}
/>
</label>
<br />
<label>
Number of guests:
<input
name="numberOfGuests"
type="number"
value={formData.numberOfGuests}
onChange={handleChange}
/>
</label>
<br />
<button type="submit">Submit</button>
</form>
);
}
export default Reservation;
formData to manage all input values.handleChange function updates the state based on the input's name attribute, making it reusable for multiple inputs.Formik or React Hook Form for complex validation needs.Handling forms in React is a crucial skill for building interactive web applications. Whether you choose controlled or uncontrolled components, understanding the underlying concepts will help you build robust and maintainable forms. By following best practices and leveraging React's powerful features, you can create seamless user experiences.