JS Guide
HomeQuestionsTopicsCompaniesResources
BookmarksSearch

Built for developers preparing for JavaScript, React & TypeScript interviews.

ResourcesQuestionsSupport
HomeQuestionsSearchProgress
HomeTopicsreactForms
PrevNext
react
intermediate
10 min read

Forms

controlled
form-actions
forms
inputs
react-hook-form
refs
uncontrolled

Controlled components use React state as the single source of truth for input values, while uncontrolled components let the DOM manage state and use refs to read values — each has tradeoffs for performance and complexity.

Key Points

1Controlled Components

React state drives input value via value + onChange — single source of truth with full control, but re-renders on every keystroke.

2Uncontrolled Components

DOM manages state, read via refs with defaultValue — fewer re-renders but less real-time control over input values.

3When to Use Each

Controlled for validation/dynamic forms/formatting. Uncontrolled for simple forms, file inputs, and performance-sensitive cases.

4Form Libraries

React Hook Form (uncontrolled, performant) and Formik (controlled, simpler). Both support Yup/Zod schema validation.

5React 19 Form Actions

Server-side form handling with <form action={fn}>, useActionState, and useFormStatus — shifting toward uncontrolled patterns.

What You'll Learn

  • Explain the difference between controlled and uncontrolled components
  • Know when to use each approach and their performance tradeoffs
  • Understand how React 19 form actions change form handling patterns

Deep Dive

Forms in React require a deliberate choice about who owns the input state — React or the DOM. This choice affects performance, validation capabilities, and code complexity.

Controlled Components

In a controlled component, React state drives the input value. Every keystroke triggers an onChange handler that updates state, and the input's value prop always reflects that state. React is the "single source of truth."

JavaScript
const [name, setName] = useState('');
<input value={name} onChange={e => setName(e.target.value)} />

Advantages: instant access to the current value for validation, formatting, conditional rendering, and submission. You can enforce input rules (max length, allowed characters) by transforming the value in the handler. Every character the user types is under your control.

Disadvantage: every keystroke triggers a state update and re-render. For simple forms this is negligible, but in forms with many fields or expensive renders, it can cause noticeable lag.

Uncontrolled Components

In an uncontrolled component, the DOM maintains its own state. You don't set a value prop — instead, you read the value when needed using a ref:

HTML
const inputRef = useRef();
<input ref={inputRef} defaultValue="" />
<button onClick={() => console.log(inputRef.current.value)}>Submit</button>

Note: use defaultValue (not value) to set the initial value without making it controlled.

Advantages: fewer re-renders (React doesn't know about keystrokes), simpler code for basic forms, required for file inputs (<input type="file" /> cannot be controlled). Disadvantage: you can't reactively validate or transform input as the user types without additional wiring.

When to Use Each

  • Controlled: real-time validation, dynamic form behavior (showing/hiding fields based on input), input formatting (phone numbers, credit cards), instant search, any form where React needs to know the value at all times.
  • Uncontrolled: simple forms where you only need values on submit, file upload inputs, integrating with non-React DOM libraries, or when you need to minimize re-renders.

Form Libraries

For complex forms, libraries handle boilerplate:

  • React Hook Form: uncontrolled approach using refs and the DOM. Minimal re-renders, excellent performance. Uses register function to connect inputs and handleSubmit for validation.
  • Formik: controlled approach with React state. More re-renders but simpler mental model. Provides Field, Form, and ErrorMessage components.

Both support schema validation with Yup or Zod.

React 19 Form Actions

React 19 introduces server-side form handling: <form action={serverAction}> submits directly to a server function. useActionState manages the form's pending/error/success states. useFormStatus lets submit buttons show loading indicators. This shifts toward uncontrolled patterns where the form data is read from the FormData object on submission rather than tracked in state.

Key Interview Distinction

Controlled = React state owns the input value (full control, more re-renders). Uncontrolled = DOM owns the value, read via refs (less control, fewer re-renders). Controlled for validation and dynamic forms, uncontrolled for simple forms and file inputs. React 19's form actions are pushing the ecosystem toward uncontrolled patterns with server-side processing.

Fun Fact

File inputs (<input type='file' />) can never be controlled in React because browsers don't allow JavaScript to set a file input's value for security reasons — it would enable web pages to read arbitrary files from the user's computer. This is one of the few cases where uncontrolled is the only option.

Learn These First

State

beginner

Hooks

intermediate

Continue Learning

State

beginner

Hooks

intermediate

Performance Optimization

advanced

Practice What You Learned

What is the difference between controlled and uncontrolled components in React forms?
mid
forms
Controlled components have their form data managed by React state - the input value is always driven by state. Uncontrolled components let the DOM handle form data using refs to access values when needed. Controlled components are recommended for most cases.
Build an OTP (One-Time Password) input component in React that auto-advances focus between fields, supports paste, and handles backspace navigation.
mid
machine-coding
An OTP input renders N separate single-character inputs with automatic focus management — advancing on input, reversing on backspace, and handling clipboard paste to distribute digits across all fields.
Previous
Error Boundaries
Next
React Fundamentals
PrevNext