In React, forms can be created using either controlled or uncontrolled components. Understanding the difference between the two is essential for managing form state and user inputs effectively.
Controlled components are those where the form data is handled by the React component's state. The state becomes the "single source of truth" for the input elements.
import React, { useState } from 'react';
const ControlledForm = () => {
const [inputValue, setInputValue] = useState('');
const handleChange = (event) => {
setInputValue(event.target.value);
};
const handleSubmit = (event) => {
event.preventDefault();
alert(`Input value: ${inputValue}`);
};
return (
<form onSubmit={handleSubmit}>
<label>
Input:
<input type="text" value={inputValue} onChange={handleChange} />
</label>
<button type="submit">Submit</button>
</form>
);
};
export default ControlledForm;
In controlled components, the input's value is always driven by the React state, making it easy to enforce validation and manipulate the input programmatically.
Uncontrolled components rely on the DOM to handle form data. Instead of using state, refs are used to access the input's value directly from the DOM.
import React, { useRef } from 'react';
const UncontrolledForm = () => {
const inputRef = useRef(null);
const handleSubmit = (event) => {
event.preventDefault();
alert(`Input value: ${inputRef.current.value}`);
};
return (
<form onSubmit={handleSubmit}>
<label>
Input:
<input type="text" ref={inputRef} />
</label>
<button type="submit">Submit</button>
</form>
);
};
export default UncontrolledForm;
Uncontrolled components can be simpler to implement, but they provide less control over the form data and can be harder to debug.
Consider using controlled components when building complex forms where validation and interactivity are crucial. Use uncontrolled components for simpler forms where quick and easy implementation is needed.
Sometimes, a hybrid approach can be used, combining both controlled and uncontrolled components to balance performance and control.
import React, { useState, useRef } from 'react';
const HybridForm = () => {
const [formData, setFormData] = useState({ email: '' });
const inputRef = useRef(null);
const handleChange = (event) => {
setFormData({ ...formData, [event.target.name]: event.target.value });
};
const handleSubmit = (event) => {
event.preventDefault();
alert(`Email: ${formData.email}, Name: ${inputRef.current.value}`);
};
return (
<form onSubmit={handleSubmit}>
<label>
Email:
<input
type="email"
name="email"
value={formData.email}
onChange={handleChange}
/>
</label>
<br />
<label>
Name:
<input type="text" ref={inputRef} />
</label>
<br />
<button type="submit">Submit</button>
</form>
);
};
export default HybridForm;
The hybrid approach can be useful when you need to control certain inputs but want to keep others simple and unmanaged.
Both controlled and uncontrolled components have their use cases and benefits. Controlled components offer more control and are ideal for complex forms, while uncontrolled components are simpler and can be useful for quick, straightforward forms.
Objective: Create a controlled and an uncontrolled form component to understand the differences in implementation and use cases.
Create a Controlled Form Component:
Create a new file ControlledForm.jsx
and define a controlled form component with validation.
import React, { useState } from 'react';
const ControlledForm = () => {
const [inputValue, setInputValue] = useState('');
const handleChange = (event) => {
setInputValue(event.target.value);
};
const handleSubmit = (event) => {
event.preventDefault();
if (inputValue.trim() === '') {
alert('Input cannot be empty');
} else {
alert(`Input value: ${inputValue}`);
}
};
return (
<form onSubmit={handleSubmit}>
<label>
Input:
<input type="text" value={inputValue} onChange={handleChange} />
</label>
<button type="submit">Submit</button>
</form>
);
};
export default ControlledForm;
Create an Uncontrolled Form Component:
Create a new file UncontrolledForm.jsx
and define an uncontrolled form component.
import React, { useRef } from 'react';
const UncontrolledForm = () => {
const inputRef = useRef(null);
const handleSubmit = (event) => {
event.preventDefault();
if (inputRef.current.value.trim() === '') {
alert('Input cannot be empty');
} else {
alert(`Input value: ${inputRef.current.value}`);
}
};
return (
<form onSubmit={handleSubmit}>
<label>
Input:
<input type="text" ref={inputRef} />
</label>
<button type="submit">Submit</button>
</form>
);
};
export default UncontrolledForm;
By completing this task, you'll gain practical experience in implementing and using both controlled and uncontrolled components in React.