ProgramGuru

Controlled Inputs

Controlled Inputs

A teacher edits a student’s name and wants the greeting on the page to match each change immediately. The text field and the greeting need one agreed current value.

A controlled input receives its current value from React state and reports edits through onChange. React state becomes the source used both for the field value and for other descriptions of that value.

  1. Understand

    Connect value and onChange to a string state variable.

  2. Build

    Update the field synchronously as the teacher types.

  3. Check

    Keep editable drafts distinct from saved student records.

An edit returns through state

  1. Display

    The input receives the current name.

  2. Edit

    onChange reads the field’s new text.

  3. Update

    State supplies the next field value and greeting.

Read this relationship alongside the complete code. This diagram explains the flow; it does not execute React.

Describe both directions of the relationship

Passing value controls what the input displays. Passing onChange tells React how the application should respond when the browser reports an edit. These belong together for an editable controlled field. Without an update, React continues supplying the previous value and the teacher’s edit appears to be rejected.

A text input supplies a string, even when its contents look like a number. Keep an empty field representable as an empty string. For a marks field, conversion and range checking belong to a deliberate validation step rather than turning every temporary edit into a number immediately.

Keep the student greeting in agreement

The input starts with Asha in name state. The label wraps the field, giving it an accessible name. Every onChange stores the new string. The greeting reads the same name and displays a helpful empty-field message instead of an unexplained blank space.

React · JavaScript with JSX

import { useState } from 'react';
export default function App() {
  const [name, setName] = useState('Asha');
  return <main><h1>Student greeting</h1>
    <label>Student name <input value={name} onChange={event => setName(event.target.value)} /></label>
    <p>Hello, {name || 'enter a student name'}!</p>
  </main>;
}

Expected screen and behavior

The field contains Asha and the greeting says Hello, Asha! Replacing the field text with Ravi changes the greeting to Hello, Ravi!

Read one keystroke as a state request

React · Keep the student greeting in agreement

import { useState } from 'react';
export default function App() {
  const [name, setName] = useState('Asha');
  return <main><h1>Student greeting</h1>
    <label>Student name <input value={name} onChange={event => setName(event.target.value)} /></label>
    <p>Hello, {name || 'enter a student name'}!</p>
  </main>;
}

Suppose the teacher replaces Asha with Ravi. The browser reports the changed input value, and the handler reads event.target.value while handling that edit. setName requests the next state. React renders with Ravi, supplies Ravi to the input value prop and calculates the matching greeting.

The onChange handler updates the controlled value directly rather than waiting for a timer or network response. A delayed value update can make typing difficult because the application keeps sending an older string to the field. Slow work such as searching a school directory can use this draft string separately without delaying the field’s immediate update.

Editing does not mean saving

An editable name is often a draft. It can change on every keystroke while the official student record stays unchanged until a Save action. Naming the value draftName makes that distinction explicit. If the requirement is only to read the value at submission, an uncontrolled field with a defaultValue and FormData is another valid design.

Controlled fields are useful when the interface needs a live preview, coordinated values or application-controlled resets. Do not choose controlled state merely because a form exists. Choose the design that supports the teacher’s actual workflow and makes ownership clear.

Try the school task

React · starting example

import { useState } from 'react';
export default function App() {
  const [name, setName] = useState('Asha');
  return <main><h1>Student greeting</h1>
    <label>Student name <input value={name} onChange={event => setName(event.target.value)} /></label>
    <p>Hello, {name || 'enter a student name'}!</p>
  </main>;
}

Add a saved-name display and a Save name button. Typing Ravi should change the draft greeting but leave Saved name: Asha unchanged. Clicking Save name should copy the non-empty trimmed draft into the saved display. Make the complete example work without a server.

Worked answer

The answer deliberately has two values because draft and saved name represent different stages of the teacher’s work. This is not accidental duplication. The event handler validates the draft and commits it to the local saved display only when the teacher requests that action.

React · JavaScript with JSX

import { useState } from 'react';
export default function App() {
  const [draftName, setDraftName] = useState('Asha');
  const [savedName, setSavedName] = useState('Asha');
  function saveName() {
    if (draftName.trim()) setSavedName(draftName.trim());
  }
  return <main><h1>Name draft</h1>
    <label>Student name <input value={draftName} onChange={event => setDraftName(event.target.value)} /></label>
    <p>Draft: {draftName || '(empty)'}</p><p>Saved name: {savedName}</p>
    <button onClick={saveName}>Save name</button>
  </main>;
}

Expected screen and behavior

Editing changes only Draft. Save name copies a non-empty trimmed value into Saved name. This local display resets after refresh.

Mistakes and boundaries

Start controlled text state with a string rather than undefined or null. Switching a field between uncontrolled and controlled behavior can produce warnings and confusing ownership. Use readOnly if the application intentionally supplies a value that the teacher may not edit.

Do not use value for the checked state of a checkbox; checkboxes use checked and event.target.checked. Avoid replacing a field’s identity during ordinary typing, because a changing key can remove and recreate the input, disturbing focus and caret position.

Check your reasoning

React · Keep the student greeting in agreement

import { useState } from 'react';
export default function App() {
  const [name, setName] = useState('Asha');
  return <main><h1>Student greeting</h1>
    <label>Student name <input value={name} onChange={event => setName(event.target.value)} /></label>
    <p>Hello, {name || 'enter a student name'}!</p>
  </main>;
}

Choose the answer that follows the data and the interaction, then read the explanation for each alternative.

The teacher types Ravi, but a field has value={name} with no onChange update. Why can the text appear to revert?
Choose one answer. You can try again.

Answer and explanation

React continues supplying the unchanged name state as the controlled value.

Correct. An editable controlled input needs an onChange handler that updates its controlling value.

Carry the idea forward

A controlled field reads from state and sends edits back through an event handler. Preserve temporary strings and separate drafts from saved data when the workflow requires it. Next, control checkboxes and selects with the properties appropriate to those controls.

Read the primary reference: React: input reference.

Reaching the recap and completing the quizzes are separate milestones.

    Next lesson: Checkboxes and Selects →