One of the key concepts in React is how to manage form elements and their state. This is typically done using either controlled or uncontrolled components. Understanding the differences between these two approaches is crucial for building effective and maintainable React applications.
Controlled components
Controlled components are those where React handles the form data through its state.
This means that form data is maintained in the component’s state and changes to the form data are handled by event handlers in React. Whenever the user interacts with the input, the component’s state is updated, and React re-renders the component to reflect the new state.
Here’s an example of a controlled input component:
import React, { useState } from 'react';
function ControlledInput() {
const [value, setValue] = useState('');
const handleChange = (event) => {
setValue(event.target.value);
};
return (
<input
type="text"
value={value}
onChange={handleChange}
/>
);
}
In this example, the value
of the input is controlled by the component’s state, which is managed by React. Whenever the user types into the input, the handleChange
function is called, which updates the value
state, causing React to re-render the component with the new value.
Uncontrolled Components
Uncontrolled components are those where the form data is handled by the DOM itself.
In other words, the form data is stored in the DOM rather than in the component’s state. To access the form data, we use refs.
import React, { useRef } from 'react';
function UncontrolledInput() {
const fileInputRef = useRef(null);
const handleSubmit = (event) => {
event.preventDefault();
const formData = new FormData();
formData.append('profilePicture', fileInputRef.current.files[0]);
// Simulate a form submission
};
return (
<form onSubmit={handleSubmit}>
<div>
<label htmlFor="profilePicture">Profile Picture:</label>
<input type="file" id="profilePicture" ref={fileInputRef} />
</div>
<button type="submit">Upload Profile</button>
</form>
);
}
In this example, the value
of the input is not directly managed by React. Instead, we use a ref (fileInputRef
) to access the current value of the input when the form is submitted.
Differences between controlled and uncontrolled components
Feature | Controlled Components | Uncontrolled Components |
---|---|---|
Data Handling | Managed by React state | Managed by the DOM |
State Management | Uses component state (useState, setState) | Uses refs to access form values |
Form Validation | Easier to implement, as data is in state | More complex, as we need to access DOM directly |
Default Values | Set via React state | Set via defaultValue attribute in JSX |
Event Handling | Requires onChange handlers to update state | No need for onChange handlers to update state |
Re-rendering | Component re-renders on every change in input value | Does not re-render on input changes |
Complexity | More code required for state management and event handling | Does not re-render on input changes |
Single Source of Truth | React component state | DOM element |
Use Case | Complex forms with dynamic interactions and validations | Simple forms with basic input handling |
Performance | Can be less performant due to frequent re-renders | Potentially more performant for simple forms |
Which Should We Use?
Choosing between controlled and uncontrolled components depends on our specific use case.
Use Controlled Components When:
- We need tight control over the form data and validation.
- We want to provide real-time feedback and validation to the user.
- We have complex forms with interdependent fields.
Use Uncontrolled Components When:
- We have simple forms with minimal validation requirements.
- We are quickly prototyping or building a small application.
- We are integrating with non-React code that expects traditional DOM-based form handling.
In general, controlled components are the preferred approach in most React applications, as they provide more predictability and control over the form data.
However, uncontrolled components can be a valid choice in certain situations, especially for simpler forms or when integrating with non-React code.
Conclusion
Both controlled and uncontrolled components have their place in React development. Controlled components offer greater control and are better suited for complex forms and data handling, while uncontrolled components can be simpler and more suitable for straightforward use cases.
By choosing the right approach for our specific requirements, we can ensure that our forms are easy to manage, validate, and integrate with the rest of our application.