Hello Sunil
mastering-uncontrolled-components-react-feature-image

Mastering Uncontrolled Components in React: Full Guide with Practical Examples

In React, we handle form inputs in two main ways: controlled and uncontrolled components. Uncontrolled components are inputs managed directly by the DOM instead of React state. We let the DOM take care of form data while accessing it via refs only when needed. This approach can simplify code, especially for simple forms.

Also Read: Controlled vs. Uncontrolled Components in React

Let’s dive into how to handle various input types as uncontrolled components with easy-to-follow examples.

Text inputs are straightforward. Instead of binding the input value to state, we use a ref to get its value when necessary.

TextInput.js

import React, { useRef } from 'react';

const TextInput = () => {
	const inputRef = useRef(null);

  const handleSubmit = () => {
    console.log("Text Input Value:", inputRef.current.value);
  };
	return (
		<div>
      <input type="text" ref={inputRef} placeholder="Enter text" />
      <button onClick={handleSubmit}>Submit</button>
    </div>
	)
}

export default TextInput

Here, inputRef.current.value fetches the text input value. React doesn’t control the input; the DOM does, which makes it “uncontrolled.”

Output:

handling-text-input-uncontrolled-components-img-1

For email input, the setup is identical to text input. Use the type="email" attribute to enforce email format.

EmailInput.js

"use client"
import React, { useRef } from 'react';

const EmailInput = () => {
	const emailRef = useRef(null);

  const handleSubmit = () => {
    console.log("Email Input Value:", emailRef.current.value);
  };
	return (
		<div>
      <input type="email" ref={emailRef} placeholder="Enter email" />
      <button onClick={handleSubmit}>Submit</button>
    </div>
	)
}

export default EmailInput

Here, using emailRef.current.value, you get the email input value only on form submission.

Output:

handling-email-input-uncontrolled-components-img-2

The approach for password input is the same as text and email but with type="password".

PasswordInput

"use client"
import React, { useRef } from 'react';

const PasswordInput = () => {
	const passwordRef = useRef(null);

	const handleSubmit = () => {
		console.log("Password Input Value:", passwordRef.current.value);
	};
	return (
		<div>
			<input type="password" ref={passwordRef} placeholder="Enter password" />
			<button onClick={handleSubmit}>Submit</button>
		</div>
	)
}

export default PasswordInput

This provides privacy by masking the characters as they are typed.

For checkboxes, we use checked property to know if it’s selected or not.

CheckboxInput

"use client"
import React, { useRef } from 'react';

const CheckboxInput = () => {
	const checkboxRef = useRef(null);

	const handleSubmit = () => {
		console.log("Checkbox Checked:", checkboxRef.current.checked);
	};
	return (
		<div>
			<input type="checkbox" ref={checkboxRef} />
			<label>Accept Terms</label>
			<button onClick={handleSubmit}>Submit</button>
		</div>
	)
}

export default CheckboxInput

Using checkboxRef.current.checked, you can check if the box is selected, which returns true or false.

Output:

handling-checkbox-uncontrolled-components-img-3

For radio buttons, multiple buttons in the same group need the same name attribute to work correctly.

RadioButtons.js

"use client"
import React, { useRef } from 'react';

const RadioButtons = () => {
	const option1Ref = useRef(null);
	const option2Ref = useRef(null);

	const handleSubmit = () => {
		console.log("Option 1 Selected:", option1Ref.current.checked);
		console.log("Option 2 Selected:", option2Ref.current.checked);
	};
	return (
		<div>
			<input type="radio" name="options" ref={option1Ref} /> Option 1
			<input type="radio" name="options" ref={option2Ref} /> Option 2
			<button onClick={handleSubmit}>Submit</button>
		</div>
	)
}

export default RadioButtons

Here, option1Ref.current.checked and option2Ref.current.checked tell which option is selected.

Output:

In a dropdown, the selected option can be accessed through the dropdown ref.

Dropdown.js

"use client"
import React, { useRef } from 'react';

const Dropdown = () => {
	const dropdownRef = useRef(null);

  const handleSubmit = () => {
    console.log("Selected Option:", dropdownRef.current.value);
  };
	return (
		<div>
      <select ref={dropdownRef}>
        <option value="option1">Option 1</option>
        <option value="option2">Option 2</option>
        <option value="option3">Option 3</option>
      </select>
      <button onClick={handleSubmit}>Submit</button>
    </div>
	)
}

export default Dropdown

With dropdownRef.current.value, you get the value of the selected option when needed.

Output:

handling-dropdowns-uncontrolled-components-img-5

To handle multiple fields, use a ref for each one and access them individually on submit.

MultiFieldForm.js

"use client"
import React, { useRef } from 'react';

const MultiFieldForm = () => {
	const nameRef = useRef(null);
  const emailRef = useRef(null);
  const passwordRef = useRef(null);

  const handleSubmit = () => {
    console.log("Name:", nameRef.current.value);
    console.log("Email:", emailRef.current.value);
    console.log("Password:", passwordRef.current.value);
  };


	return (
		<div>
      <input type="text" ref={nameRef} placeholder="Name" />
      <input type="email" ref={emailRef} placeholder="Email" />
      <input type="password" ref={passwordRef} placeholder="Password" />
      <button onClick={handleSubmit}>Submit</button>
    </div>
	)
}

export default MultiFieldForm

Each field value is accessed individually through its ref, making this approach simple and efficient for small forms.

Output:

handling-multiple-form-fields-uncontrolled-components-img-6

Uncontrolled components can make forms easier to handle in situations where you don’t need real-time control of input values. They let the DOM handle state, making them ideal for simple form inputs or when working with external libraries.

With refs, accessing input values when you need them is straightforward, keeping your React component code clean and efficient.

How useful was this post?

Click on a star to rate it!

Average rating 0 / 5. Vote count: 0

No votes so far! Be the first to rate this post.

We are sorry that this post was not useful for you!

Let us improve this post!

Tell us how we can improve this post?

Similar articles you may like

Sunil Pradhan

Hi there đź‘‹ I am a front-end developer passionate about cutting-edge, semantic, pixel-perfect design. Writing helps me to understand things better.

Add comment

Stay Updated

Want to be notified when our article is published? Enter your email address below to be the first to know.

Sunil Pradhan

Hi there đź‘‹ I am a front-end developer passionate about cutting-edge, semantic, pixel-perfect design. Writing helps me to understand things better.