Uncontrolled Components in React JS
Uncontrolled Components are form elements in React JS whose current values are managed by the DOM rather than being controlled by React state. React can provide an initial value using attributes such as defaultValue and defaultChecked. When the user changes the input, the DOM maintains its current value.
React developers can access the current values of uncontrolled form elements using the useRef() Hook, DOM references, or the browser's FormData API when the form is submitted.
Uncontrolled components are useful for simple forms, file uploads, and situations where input values only need to be read when a form is submitted.
Course Link: JustAcademy React JS Training Course
Demo Link: Register for React JS Course Demo
1. What Are Uncontrolled Components?
An uncontrolled component is a form element whose current value is maintained by the browser's DOM. Unlike a controlled component, it does not require React state to be updated on every keystroke.
For example, a text input can have an initial value, but users can change it directly in the browser. React does not control the input's current value through a state variable.
Example
function NameForm() {
return (
<form>
<label htmlFor="name">Enter your name:</label>
<input
id="name"
name="name"
type="text"
defaultValue="Amit"
/>
</form>
);
}
export default NameForm;
In this example, the input initially displays "Amit". The user can edit the text, and the browser maintains the current value without using React state.
2. How Uncontrolled Components Work
Uncontrolled components rely on the DOM to maintain input values. React can specify the initial value, while the browser handles subsequent user edits.
- Render the input: Create a form element in JSX.
- Set an initial value: Use
defaultValue or defaultChecked when needed.
- User changes the field: The browser updates the input's current value.
- Read the value: Use a ref or FormData when the value is needed.
- Process the form: Handle the form submission or perform another required action.
Basic Flow
React renders the form element
↓
Browser maintains the current input value
↓
User enters or changes information
↓
DOM stores the updated value
↓
React reads the value using a ref or FormData
↓
Application processes the form data
3. Understanding defaultValue
The defaultValue prop specifies the initial value of an uncontrolled text input or textarea. It does not continuously control the field after the element has mounted.
Example
function UsernameForm() {
return (
<div>
<label htmlFor="username">Username:</label>
<input
id="username"
name="username"
type="text"
defaultValue="Guest"
/>
</div>
);
}
export default UsernameForm;
The input initially displays "Guest". If the user changes it to "Rahul", the browser maintains "Rahul" as the current value. Changing the defaultValue prop after mounting does not control the current input value.
Important Points
defaultValue sets the initial value.
- The browser maintains subsequent changes.
- It is commonly used with uncontrolled text inputs and textareas.
- Use
value with state when React must control the current value.
4. Accessing Input Values Using useRef()
The useRef() Hook creates a reference that can point to a DOM element. By assigning the ref to an input's ref prop, you can read its current value when needed.
Syntax
const inputRef = useRef(null);
After React mounts the input, inputRef.current refers to the DOM input element. Its current text can be accessed through inputRef.current.value.
Example
import { useRef } from "react";
function NameForm() {
const nameRef = useRef(null);
function handleSubmit(event) {
event.preventDefault();
alert("Entered name: " + nameRef.current.value);
}
return (
<form onSubmit={handleSubmit}>
<label htmlFor="name">Name:</label>
<input
id="name"
name="name"
type="text"
ref={nameRef}
defaultValue="Amit"
/>
<button type="submit">Submit</button>
</form>
);
}
export default NameForm;
How It Works
useRef(null) creates a ref object.
- The
ref prop connects the ref to the input element.
- The user enters or edits the name.
- When the form is submitted,
nameRef.current.value reads the current value.
- The value can then be processed or sent to a backend.
5. Accessing Multiple Input Values with Refs
When a form contains several uncontrolled inputs, you can create a separate ref for each field. This approach is useful when values only need to be accessed at specific moments, such as form submission.
Example
import { useRef } from "react";
function RegistrationForm() {
const nameRef = useRef(null);
const emailRef = useRef(null);
const phoneRef = useRef(null);
function handleSubmit(event) {
event.preventDefault();
const formData = {
name: nameRef.current.value,
email: emailRef.current.value,
phone: phoneRef.current.value
};
console.log(formData);
}
return (
<form onSubmit={handleSubmit}>
<input
name="name"
ref={nameRef}
defaultValue=""
placeholder="Full name"
/>
<input
name="email"
type="email"
ref={emailRef}
defaultValue=""
placeholder="Email address"
/>
<input
name="phone"
type="tel"
ref={phoneRef}
defaultValue=""
placeholder="Phone number"
/>
<button type="submit">Register</button>
</form>
);
}
export default RegistrationForm;
Each ref provides access to its corresponding DOM element. When the form is submitted, the current values are collected into a JavaScript object.
6. Reading Form Values Using FormData
The browser's FormData API is another convenient way to read values from uncontrolled forms. It collects the values of form controls that have appropriate name attributes.
Example
function ContactForm() {
function handleSubmit(event) {
event.preventDefault();
const formData = new FormData(event.currentTarget);
const name = formData.get("name");
const email = formData.get("email");
console.log("Name:", name);
console.log("Email:", email);
}
return (
<form onSubmit={handleSubmit}>
<label htmlFor="name">Name:</label>
<input
id="name"
name="name"
defaultValue=""
required
/>
<label htmlFor="email">Email:</label>
<input
id="email"
name="email"
type="email"
defaultValue=""
required
/>
<button type="submit">Submit</button>
</form>
);
}
export default ContactForm;
How FormData Works
event.preventDefault() prevents the browser's default form navigation.
new FormData(event.currentTarget) collects the form's named field values.
formData.get("name") retrieves the value associated with the name field.
- The collected values can be validated, displayed, or sent to a server.
Important: Every field you want to retrieve must have a suitable name attribute. Unchecked checkboxes are not included in the submitted FormData entries.
7. Uncontrolled Text Inputs
Uncontrolled text inputs are useful when the application only needs to read the entered value when an action occurs, rather than update React state on every keystroke.
Example
function SearchForm() {
function handleSubmit(event) {
event.preventDefault();
const formData = new FormData(event.currentTarget);
const searchTerm = formData.get("search");
console.log("Search term:", searchTerm);
}
return (
<form onSubmit={handleSubmit}>
<input
name="search"
type="text"
placeholder="Enter search term"
/>
<button type="submit">Search</button>
</form>
);
}
export default SearchForm;
The browser maintains the input value. When the user submits the form, the application reads the search term using FormData.
8. Uncontrolled Textarea
A textarea collects multiline text such as comments, feedback, or descriptions. An uncontrolled textarea can use defaultValue to set its initial text.
Example
function FeedbackForm() {
function handleSubmit(event) {
event.preventDefault();
const formData = new FormData(event.currentTarget);
const feedback = formData.get("feedback");
alert("Feedback: " + feedback);
}
return (
<form onSubmit={handleSubmit}>
<label htmlFor="feedback">Your Feedback:</label>
<textarea
id="feedback"
name="feedback"
defaultValue=""
rows={4}
placeholder="Write your feedback"
/>
<button type="submit">Submit Feedback</button>
</form>
);
}
export default FeedbackForm;
The browser maintains the text entered by the user. The current value is read when the form is submitted.
9. Uncontrolled Select Dropdown
A select dropdown allows users to choose an option from a list. In an uncontrolled select element, defaultValue specifies the initially selected option.
Example
function CourseForm() {
function handleSubmit(event) {
event.preventDefault();
const formData = new FormData(event.currentTarget);
const course = formData.get("course");
alert("Selected course: " + course);
}
return (
<form onSubmit={handleSubmit}>
<label htmlFor="course">Select Course:</label>
<select
id="course"
name="course"
defaultValue="react"
>
<option value="react">React JS</option>
<option value="flutter">Flutter</option>
<option value="selenium">Selenium</option>
</select>
<button type="submit">Submit</button>
</form>
);
}
export default CourseForm;
The dropdown initially selects React JS. Users can select a different option, and the current selection is read on submission.
10. Uncontrolled Checkboxes
An uncontrolled checkbox can use defaultChecked to specify its initial selection state. The browser maintains its current checked state after the user interacts with it.
Example
function TermsForm() {
function handleSubmit(event) {
event.preventDefault();
const formData = new FormData(event.currentTarget);
const accepted = formData.get("terms") === "accepted";
alert(accepted ? "Terms accepted" : "Please accept the terms");
}
return (
<form onSubmit={handleSubmit}>
<label>
<input
type="checkbox"
name="terms"
value="accepted"
defaultChecked={false}
/>
I accept the terms and conditions
</label>
<button type="submit">Continue</button>
</form>
);
}
export default TermsForm;
In this example, the checkbox starts unchecked. If selected, its value is included in FormData. If it remains unchecked, the field is omitted.
11. Uncontrolled Radio Buttons
Radio buttons let users choose one option from a group. Uncontrolled radio buttons can use defaultChecked to set the initially selected option.
Example
function PaymentForm() {
function handleSubmit(event) {
event.preventDefault();
const formData = new FormData(event.currentTarget);
const payment = formData.get("payment");
alert("Payment method: " + payment);
}
return (
<form onSubmit={handleSubmit}>
<label>
<input
type="radio"
name="payment"
value="card"
defaultChecked
/>
Card
</label>
<label>
<input
type="radio"
name="payment"
value="upi"
/>
UPI
</label>
<button type="submit">Submit</button>
</form>
);
}
export default PaymentForm;
Both radio buttons share the same name, so the user can select only one option. The chosen value is read using FormData.
12. File Inputs in React
File inputs are commonly used for uploading images, documents, resumes, and other files. In React, a file input is treated as uncontrolled because its selected file value cannot be set programmatically like a normal text input.
Use a ref to access the DOM element and its files property, or read the selected file using FormData.
Example
import { useRef } from "react";
function FileUploadForm() {
const fileRef = useRef(null);
function handleSubmit(event) {
event.preventDefault();
const file = fileRef.current.files[0];
if (!file) {
alert("Please select a file.");
return;
}
alert("Selected file: " + file.name);
}
return (
<form onSubmit={handleSubmit}>
<label htmlFor="document">Choose a document:</label>
<input
id="document"
name="document"
type="file"
ref={fileRef}
/>
<button type="submit">Upload</button>
</form>
);
}
export default FileUploadForm;
This example reads the selected file's name. It does not upload the file to a server. Actual uploads require additional handling, such as sending the file through a request using FormData.
13. Controlled vs. Uncontrolled Components
Both approaches can be used to create forms in React. The appropriate choice depends on how the application needs to manage and use the form values.
| Feature |
Controlled Components |
Uncontrolled Components |
| Value management |
React state |
DOM |
| Common props |
value, checked |
defaultValue, defaultChecked |
| Reading values |
From state variables |
Using refs or FormData |
| State updates while typing |
Usually yes |
Not required |
| Live validation |
Convenient to implement |
Requires additional handling |
| Code complexity |
Can require more state and handlers |
Often simpler for basic forms |
| File inputs |
Cannot control the selected file value normally |
Commonly used with refs or FormData |
| Best suited for |
Forms with live feedback or state-dependent UI |
Simple forms whose values are read when needed |
Controlled Example
const [name, setName] = useState("");
<input
value={name}
onChange={(event) => setName(event.target.value)}
/>
Uncontrolled Example
<input name="name" defaultValue="" />
In the controlled example, React state determines the current value. In the uncontrolled example, the browser maintains the current value.
14. Form Validation with Uncontrolled Components
Uncontrolled components can use built-in HTML validation attributes and custom validation when the form is submitted. Common attributes include required, minLength, maxLength, and suitable input types.
Example
function RegistrationForm() {
function handleSubmit(event) {
event.preventDefault();
const formData = new FormData(event.currentTarget);
const name = formData.get("name").trim();
const email = formData.get("email");
if (!name) {
alert("Please enter your name.");
return;
}
if (!email) {
alert("Please enter your email.");
return;
}
alert("Form validation completed.");
}
return (
<form onSubmit={handleSubmit}>
<input
name="name"
placeholder="Full name"
required
/>
<input
name="email"
type="email"
placeholder="Email address"
required
/>
<button type="submit">Register</button>
</form>
);
}
export default RegistrationForm;
The browser checks the required fields and email format before normal form submission. The custom handler then reads and validates the submitted values. Client-side validation improves usability, but important rules must also be checked on the server.
15. Resetting an Uncontrolled Form
Uncontrolled forms can be reset using the browser's native form reset behavior. A reset restores the controls to their initial values, including values specified by defaultValue and defaultChecked.
Example
function ResetForm() {
return (
<form onSubmit={(event) => event.preventDefault()}>
<input
name="name"
defaultValue="Amit"
placeholder="Name"
/>
<input
name="email"
type="email"
defaultValue=""
placeholder="Email"
/>
<button type="submit">Submit</button>
<button type="reset">Reset</button>
</form>
);
}
export default ResetForm;
Clicking Reset restores the name field to "Amit" and the email field to an empty string.
16. Common Mistakes in Uncontrolled Components
- Using
value when the intention is to create an uncontrolled input. Use defaultValue for an initial value.
- Using
checked instead of defaultChecked when you do not want React to control the checkbox or radio button.
- Forgetting to provide a
name attribute when reading values through FormData.
- Trying to read a ref before React has attached the DOM element.
- Assuming that changing
defaultValue after mounting will update the current input value.
- Forgetting
event.preventDefault() when using a custom onSubmit handler to avoid the browser's default navigation.
- Trying to set a file input's selected file value programmatically.
- Assuming that data read from a form has already been saved to a database.
- Relying only on client-side validation for important data.
17. Best Practices for Uncontrolled Components
- Use uncontrolled components when values only need to be read at specific moments.
- Use
defaultValue for initial text or dropdown values.
- Use
defaultChecked for initial checkbox or radio selection.
- Use refs for direct access to a particular DOM element.
- Use FormData when reading several named fields during form submission.
- Provide meaningful labels and suitable input types.
- Use HTML validation attributes where appropriate.
- Handle missing or invalid input values gracefully.
- Validate important data on the server before saving or processing it.
- Prefer controlled components if the UI must react immediately to changes in input values.
18. Mini Project: Student Registration Form
This project demonstrates an uncontrolled form using FormData to collect a student's name, email, and selected course.
App.jsx
function App() {
function handleSubmit(event) {
event.preventDefault();
const formData = new FormData(event.currentTarget);
const name = formData.get("name").trim();
const email = formData.get("email");
const course = formData.get("course");
if (!name || !email || !course) {
alert("Please complete all required fields.");
return;
}
console.log({ name, email, course });
alert("Registration form completed for " + name);
}
return (
<main>
<h1>Student Registration</h1>
<form onSubmit={handleSubmit}>
<label htmlFor="name">Full Name:</label>
<input
id="name"
name="name"
defaultValue=""
required
/>
<label htmlFor="email">Email Address:</label>
<input
id="email"
name="email"
type="email"
defaultValue=""
required
/>
<label htmlFor="course">Select Course:</label>
<select
id="course"
name="course"
defaultValue=""
required
>
<option value="">Choose a course</option>
<option value="React JS">React JS</option>
<option value="Flutter">Flutter</option>
<option value="Selenium">Selenium</option>
</select>
<button type="submit">Register</button>
<button type="reset">Reset</button>
</form>
</main>
);
}
export default App;
Project Explanation
- Uncontrolled inputs: The form fields do not use React state for their current values.
- Initial values: The
defaultValue prop defines the initial input or dropdown value.
- Form submission: The
onSubmit handler reads the values.
- FormData: The API collects data using each field's
name attribute.
- Validation: The code checks for missing fields before displaying a success message.
- Reset: The native reset button restores the initial form values.
Note: This project is for front-end learning. It does not save registration details permanently or send them to a backend.
19. Interview Questions and Answers
Q1. What is an uncontrolled component in React?
An uncontrolled component is a form element whose current value is maintained by the DOM rather than React state.
Q2. Which props are used to set initial values in uncontrolled components?
defaultValue is used for text inputs, textareas, and select elements. defaultChecked is used for checkboxes and radio buttons.
Q3. How do you access an uncontrolled input's value?
You can use a ref to read ref.current.value or use FormData when the form is submitted.
Q4. What is the use of useRef()?
The useRef() Hook creates a reference that can be used to access a DOM element or retain a value between renders without causing a re-render when the ref changes.
Q5. What is FormData?
FormData is a browser API that collects values from named form controls and can be used to read or submit form information.
Q6. What is the difference between value and defaultValue?
value controls the current value of a form element, usually through React state. defaultValue specifies the initial value of an uncontrolled field.
Q7. Can a file input be controlled like a normal text input?
No. A file input's selected files are controlled by the user through the browser. React applications commonly access them using refs or FormData.
Q8. When should you use uncontrolled components?
They are useful for simple forms when values only need to be read during submission, for file inputs, and for certain integrations with non-React code.
Q9. Do uncontrolled components support validation?
Yes. They support browser validation attributes and custom validation when values are read from the DOM or FormData.
Q10. Do uncontrolled components save data to a database automatically?
No. They only provide access to the input values. Saving data requires additional application logic and usually a backend or data service.
20. Practice Exercises
- Create an uncontrolled input for a user's name and read it using a ref.
- Build a contact form and read its fields using FormData.
- Create a feedback form using an uncontrolled textarea.
- Build a course dropdown using
defaultValue.
- Create a checkbox for accepting terms and read its value during submission.
- Build a payment selection form using radio buttons.
- Create a file upload field and display the selected file name.
- Build a registration form with required-field validation.
- Add a Reset button that restores the form's initial values.
- Compare the same registration form implemented with controlled and uncontrolled components.
21. Revision Checklist
- Understand the definition of uncontrolled components.
- Know how the DOM maintains current form values.
- Understand
defaultValue and defaultChecked.
- Know how to access input values using
useRef().
- Understand how to read form values using FormData.
- Know how to handle text inputs, textareas, dropdowns, checkboxes, and radio buttons.
- Understand why file inputs are generally uncontrolled.
- Know how to validate and reset an uncontrolled form.
- Understand the differences between controlled and uncontrolled components.
- Practice the student registration form project.
22. Conclusion
Uncontrolled Components are a useful React JS technique for building forms in which the DOM maintains the current input values. React can provide initial values through defaultValue and defaultChecked, while refs and FormData allow applications to read the current values when required. Understanding uncontrolled components alongside controlled components helps developers choose the appropriate approach for each form and build practical React applications.
Learn more through the JustAcademy React JS Training Course.
To explore the course through a demo, visit Register for React JS Course Demo.