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.
Handling Text Input in Uncontrolled Components
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 Email Input in Uncontrolled Components
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 Password Input in Uncontrolled Components
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.
Handling Checkboxes in Uncontrolled Components
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 Radio Buttons in Uncontrolled Components
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:
Handling Dropdowns in Uncontrolled Components
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 Multiple Form Fields
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:
Conclusion
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.
Add comment