Controlled and uncontrolled components in React
In React, controlled and uncontrolled components refer to how form data is managed within the component.
Controlled Components
A controlled component is one where the form data is handled by the React component's state. The state within the component is the single source of truth for the form data.
Example of a Controlled Component:
import React, { useState } from 'react';
const ControlledForm = () => {
const [inputValue, setInputValue] = useState('');
const handleChange = (e) => {
setInputValue(e.target.value);
};
const handleSubmit = (e) => {
e.preventDefault();
alert('Submitted value: ' + inputValue);
};
return (
<form onSubmit={handleSubmit}>
<input type="text" value={inputValue} onChange={handleChange} />
<button type="submit">Submit</button>
</form>
);
};
export default ControlledForm;
In this example:
- The input field's value is controlled by the
inputValue
state. - The
handleChange
function updates the state whenever the input value changes.
Uncontrolled Components
An uncontrolled component is one where form data is handled by the DOM itself. You can access the form data using refs instead of relying on component state.
Example of an Uncontrolled Component:
import React, { useRef } from 'react';
const UncontrolledForm = () => {
const inputRef = useRef(null);
const handleSubmit = (e) => {
e.preventDefault();
alert('Submitted value: ' + inputRef.current.value);
};
return (
<form onSubmit={handleSubmit}>
<input type="text" ref={inputRef} />
<button type="submit">Submit</button>
</form>
);
};
export default UncontrolledForm;
In this example:
- The input field's value is not tied to the component state.
- The
inputRef
is used to directly access the input value from the DOM when needed.
When to Use Controlled Components
- Form Validation: When you need to validate the form data before submission.
- Dynamic Forms: When the form fields need to be dynamically enabled/disabled or shown/hidden.
- Real-time Updates: When you need real-time feedback or updates based on the input values.
- Consistency: When you need to ensure that the form data is always in sync with the component state.
Example Use Case: A registration form where you need to validate the email and password fields before submission and provide real-time feedback.
import React, { useState } from 'react';
const RegistrationForm = () => {
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const [errors, setErrors] = useState({});
const handleChange = (e) => {
const { name, value } = e.target;
if (name === 'email') {
setEmail(value);
} else if (name === 'password') {
setPassword(value);
}
};
const validate = () => {
const errors = {};
if (!email.includes('@')) {
errors.email = 'Invalid email address';
}
if (password.length < 6) {
errors.password = 'Password must be at least 6 characters';
}
setErrors(errors);
return Object.keys(errors).length === 0;
};
const handleSubmit = (e) => {
e.preventDefault();
if (validate()) {
// submit form
alert('Form submitted');
}
};
return (
<form onSubmit={handleSubmit}>
<div>
<label>Email:</label>
<input type="email" name="email" value={email} onChange={handleChange} />
{errors.email && <span>{errors.email}</span>}
</div>
<div>
<label>Password:</label>
<input type="password" name="password" value={password} onChange={handleChange} />
{errors.password && <span>{errors.password}</span>}
</div>
<button type="submit">Register</button>
</form>
);
};
export default RegistrationForm;
When to Use Uncontrolled Components
- Simple Forms: When the form is simple and doesn't require complex validation or real-time updates.
- Third-Party Libraries: When using third-party libraries that manage form state outside of React.
- Initial Values: When you need to set initial values without managing them in state.
Example Use Case: A simple search form where you just need to get the input value on form submission.
import React, { useRef } from 'react';
const SearchForm = () => {
const inputRef = useRef(null);
const handleSubmit = (e) => {
e.preventDefault();
alert('Search query: ' + inputRef.current.value);
};
return (
<form onSubmit={handleSubmit}>
<input type="text" ref={inputRef} placeholder="Search..." />
<button type="submit">Search</button>
</form>
);
};
export default SearchForm;