🚀 LEVEL UP TO SENIOR:Unlock 500+ Advanced Practical Challenges & Exercises.
🎓 COURSERA PARTNER:Earn professional Google, Meta, and IBM certificates to supercharge your resume.
REFERENCEreact

react Documentation

LOADING ENGINE...

useState in Forms

AI & DATA SCIENCE // usestate-in-forms

useState is the standard way to hold a controlled form input's current value in React, updating it via the input's onChange handler as the user types.

Syntax

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

Deep Dive Course

In the controlled-input pattern, an input's displayed value is dictated entirely by a useState value, and its onChange handler reads the new value from event.target.value and passes it to the setter, keeping the state and the input's displayed content perfectly synchronized on every keystroke. This gives the component full, immediate access to the current input value at any point, useful for showing live character counts, enabling/disabling a submit button based on the current input, or performing real-time validation, none of which are as straightforward with an uncontrolled input relying only on the DOM's own internal value.

1Understanding useState in Forms

In the controlled-input pattern, an input's displayed value is dictated entirely by a useState value, and its onChange handler reads the new value from event.target.value and passes it to the setter, keeping the state and the input's displayed content perfectly synchronized on every keystroke. This gives the component full, immediate access to the current input value at any point, useful for showing live character counts, enabling/disabling a submit button based on the current input, or performing real-time validation, none of which are as straightforward with an uncontrolled input relying only on the DOM's own internal value.

💡

A controlled text input's initial useState value should be an empty string, '', not undefined — starting undefined and switching to a string later triggers a React warning about a component changing from an uncontrolled to a controlled input.

editor.html
import { useState } from 'react';

function CommentBox() {
  const [comment, setComment] = useState('');
  return (
    <>
      <textarea value={comment} onChange={(e) => setComment(e.target.value)} />
      <p>{comment.length}/280 characters</p>
    </>
  );
}
localhost:3000

2Practical Example

Here is a real-world application of useState in Forms showing how it is used in production React code.

editor.html
import { useState } from 'react';

function SubmitForm() {
  const [name, setName] = useState('');
  return (
    <>
      <input value={name} onChange={(e) => setName(e.target.value)} />
      <button disabled={name.trim() === ''}>Submit</button>
    </>
  );
}
localhost:3000

3Best Practices

Follow these guidelines when working with useState in Forms:

1. Initialize a controlled input's state with an appropriate empty default, like '' for text or false for a checkbox, never undefined, to avoid a React warning about switching between controlled and uncontrolled

2. Read the new value from event.target.value, or event.target.checked for checkboxes, inside onChange, passing it directly to the state setter

3. Use the current state value directly for real-time UI feedback, like a live character count or a submit button that's disabled until required fields are filled

⚠️

Tip: A controlled text input's initial useState value should be an empty string, '', not undefined — starting undefined and switching to a string later triggers a React warning about a component changing from an uncontrolled to a controlled input.

editor.html
import { useState } from 'react';

function CommentBox() {
  const [comment, setComment] = useState('');
  return (
    <>
      <textarea value={comment} onChange={(e) => setComment(e.target.value)} />
      <p>{comment.length}/280 characters</p>
    </>
  );
}
localhost:3000

Examples

Example 01Basic Usage
import { useState } from 'react';

function CommentBox() {
  const [comment, setComment] = useState('');
  return (
    <>
      <textarea value={comment} onChange={(e) => setComment(e.target.value)} />
      <p>{comment.length}/280 characters</p>
    </>
  );
}
Example 02Advanced Example
import { useState } from 'react';

function SubmitForm() {
  const [name, setName] = useState('');
  return (
    <>
      <input value={name} onChange={(e) => setName(e.target.value)} />
      <button disabled={name.trim() === ''}>Submit</button>
    </>
  );
}

Best Practices

  • Initialize a controlled input's state with an appropriate empty default, like '' for text or false for a checkbox, never undefined, to avoid a React warning about switching between controlled and uncontrolled
  • Read the new value from event.target.value, or event.target.checked for checkboxes, inside onChange, passing it directly to the state setter
  • Use the current state value directly for real-time UI feedback, like a live character count or a submit button that's disabled until required fields are filled

Interview Question

Why does initializing a controlled input's state as undefined, then later setting it to an actual string, trigger a React warning about switching from uncontrolled to controlled?

Hint: Think about how React distinguishes a controlled input from an uncontrolled one based purely on what's passed to its value prop.

React determines whether an input is controlled or uncontrolled based on whether its value prop is defined at all — passing value={undefined} is treated essentially the same as not passing a value prop at all, meaning React lets the DOM manage that input's value internally, exactly like an uncontrolled input, at least for that specific render. If the component's state later updates from undefined to an actual string value, the input's value prop suddenly goes from undefined to something defined, which looks to React like the input abruptly switching from being uncontrolled to controlled partway through the component's lifetime, a transition React explicitly warns about since it usually indicates an unintentional bug rather than a deliberate design choice, and can cause inconsistent behavior around what the input actually displays. Initializing state with a proper empty value, like '' for text, from the very first render instead ensures the input is controlled consistently from the start, avoiding that warning entirely.

Exercises

MediumPractice using useState in Forms in a real scenario.
View Solution
import { useState } from 'react';

function CommentBox() {
  const [comment, setComment] = useState('');
  return (
    <>
      <textarea value={comment} onChange={(e) => setComment(e.target.value)} />
      <p>{comment.length}/280 characters</p>
    </>
  );
}

Frequently Asked Questions

Why does initializing a controlled input's state as undefined, then later setting it to an actual string, trigger a React warning about switching from uncontrolled to controlled?

React determines whether an input is controlled or uncontrolled based on whether its value prop is defined at all — passing value={undefined} is treated essentially the same as not passing a value prop at all, meaning React lets the DOM manage that input's value internally, exactly like an uncontrolled input, at least for that specific render. If the component's state later updates from undefined to an actual string value, the input's value prop suddenly goes from undefined to something defined, which looks to React like the input abruptly switching from being uncontrolled to controlled partway through the component's lifetime, a transition React explicitly warns about since it usually indicates an unintentional bug rather than a deliberate design choice, and can cause inconsistent behavior around what the input actually displays. Initializing state with a proper empty value, like '' for text, from the very first render instead ensures the input is controlled consistently from the start, avoiding that warning entirely.

Related Functions

form-handlingcontrolled-vs-uncontrolledonchange