DEV Community

Cover image for React: Optimizing Forms with Controlled and Uncontrolled Components
Reme Le Hane
Reme Le Hane

Posted on • Originally published atremejuan.substack.com

React: Optimizing Forms with Controlled and Uncontrolled Components

React forms can get complex quickly, especially as they grow in fields and complexity. Knowing when to use controlled and uncontrolled components effectively can simplify form management.

Trick: Combining Controlled and Uncontrolled Components for Form Optimization

Controlled Componentsin React are inputs that are fully controlled by React state (via useState), meaning every keystroke triggers a re-render. This is great for real-time validation but can become inefficient with large forms.

Uncontrolled Componentsuse refs to access DOM values directly without requiring state, making them faster and ideal for inputs you don’t need to validate live.

Here’s a mix of both approaches to make an optimized form that’s still easy to manage.

Example: A Mixed-Controlled Form

Let’s create a form where some fields use controlled components and others use uncontrolled components.

importReact,{useState,useRef}from"react";

constOptimizedForm=()=>{
// Controlled input for real-time validation or tracking

const[username,setUsername]=useState("");

const[error,setError]=useState("");

// Uncontrolled inputs for fields that don't need live validation
constemailRef=useRef();
constpasswordRef=useRef();

consthandleUsernameChange=(e)=>{
constvalue=e.target.value;

setUsername(value);

// Example validation
if(value.length<3){
setError("Username must be at least 3 characters.");
}else{
setError("");
}
};

consthandleSubmit=(e)=>{
e.preventDefault();

// Accessing values of uncontrolled inputs
constemail=emailRef.current.value;
constpassword=passwordRef.current.value;

// Example form submission or validation logic
console.log("Username:",username);
console.log("Email:",email);
console.log("Password:",password);
};

return(

<formonSubmit={handleSubmit}>
<div>
<label>Username(Controlled):</label>
<input
type="text"
value={username}
onChange={handleUsernameChange}
/>
{error&&<pstyle={{color:"red"}}>{error}</p>}
</div>

<div>
<label>Email(Uncontrolled):</label>
<inputtype="email"ref={emailRef}/>
</div>

<div>
<label>Password(Uncontrolled):</label>
<inputtype="password"ref={passwordRef}/>
</div>
<buttontype="submit">Submit</button>
</form>

);

};

exportdefaultOptimizedForm;
Enter fullscreen mode Exit fullscreen mode

Explanation:

  1. Controlled Component (Username):
  • We use useState to manage the username, enabling real-time validation (checking the character count).

  • This is ideal for fields that require live updates or validation.

  1. Uncontrolled Components (Email and Password):
  • We use useRef to get values directly from the DOM without managing them in state.

  • This is useful for fields like email or password where live validation might not be necessary.

  1. Form Submission:
  • On form submit, we access the values of both controlled and uncontrolled inputs seamlessly.

Why This Trick is Useful

  • Performance:Reduces re-renders by avoiding state updates for every keystroke in large forms.

  • Simplicity:Keeps form logic cleaner and more maintainable by separating fields that need validation from those that don’t.

Mastering this technique will help you balance performance and responsiveness in React forms, especially in apps with complex or large forms!

Top comments(2)

Collapse
brense profile image
Rense Bakker

You don't need refs either, you can access the form data directly from the forms onSubmit or onChange event.

Collapse
eastcoast8264 profile image
Mark M