HOWTO · React

How to Use the onChange Event in React

Learn how React onChange handlers read text, checkbox, and select input changes and keep controlled form values in sync with state.

On this page

React’s onChange prop lets a component respond to changes made through form controls. A handler reads the changed control’s value and updates the state that supplies its displayed value. React’s onChange is not simply the native HTML onchange attribute: React handles form changes through its event system, with behavior suited to React controls.

Use a controlled input when the component needs to own the current form value, validate it, or use it elsewhere in the interface. The basic pattern is to pass a state value to the control and update that state in its onChange handler.

Understanding the onChange Event

Attach a handler to an input, textarea, or select with the JSX prop onChange. For text fields and selects, read event.target.value; for checkboxes, read the boolean event.target.checked. The handler then updates the state associated with that control.

In a controlled form control, the displayed value comes from state. When the handler updates state, React renders the control with the new value. This keeps the interface and the component’s data in sync. Choose an uncontrolled control when the component does not need to manage its value during interaction.

Implementing onChange with Text Inputs

For a text input, keep a string in state, pass it through value, and update it from the event. In a class component whose state contains name, the JSX control can be written as <input value={this.state.name} onChange={event => this.setState({ name: event.target.value })} />. The state update makes the displayed text follow each edit. Keep the state value a string throughout the input’s lifetime.

The runnable JavaScript below isolates the handler logic for a text field, checkbox, and select. It uses small state setters to show which event property each handler reads; it does not render React controls. The JSX lines in this article show how to connect those values to controlled React controls.

let name = '';
let subscribed = false;
let category = 'books';

const setName = (value) => { name = value; };
const setSubscribed = (value) => { subscribed = value; };
const setCategory = (value) => { category = value; };

const handleNameChange = (event) => setName(event.target.value);
const handleSubscribedChange = (event) => setSubscribed(event.target.checked);
const handleCategoryChange = (event) => setCategory(event.target.value);

handleNameChange({ target: { value: 'Ada' } });
handleSubscribedChange({ target: { checked: true } });
handleCategoryChange({ target: { value: 'music' } });

console.log(`Name: ${name}`);
console.log(`Subscribed: ${subscribed}`);
console.log(`Category: ${category}`);
Name: Ada
Subscribed: true
Category: music

In a React component, the setters in the runnable illustration correspond to state updates. The control’s displayed value comes from that state, so React can keep the view and data synchronized.

Working with Checkboxes

A checkbox represents a boolean choice, so control its selection with checked and read event.target.checked in its handler. In a class component, a checkbox can use checked={this.state.subscribed} and onChange={event => this.setState({ subscribed: event.target.checked })}. The checkbox’s value is its submitted form value; it does not indicate whether the user selected it.

Using onChange with Select Dropdowns

For a select control, pass the selected state through value and read the next choice from event.target.value. For example, use <select value={this.state.category} onChange={event => this.setState({ category: event.target.value })}><option value="books">Books</option><option value="music">Music</option></select>. The option value is the data stored in state and may differ from its visible label. Updating state makes the selected option and any dependent interface follow the same source of truth.

Best Practices for Using onChange

Keep handlers focused on reading the event and updating the relevant state. Put validation where it fits the form’s needs: for example, validate while typing for immediate feedback, or validate on submission when feedback during entry would be distracting. Ensure the value prop and its state use a consistent type, and use checked for checkbox state.

Debouncing can help when a handler starts expensive work, such as filtering a large dataset or sending a search request. It adds delay to the response and does not automatically prevent React renders, so use it only when the work and user experience benefit. Updating controlled state for each keystroke is a normal pattern.

Programmatically changing an input’s DOM value is an advanced case. Assigning a value directly does not by itself guarantee that React will observe the change or call the expected handler. Prefer updating the state that controls the input. If external code must interact with a form control, use the component’s public interface where possible and verify behavior in that integration; helper names such as setNativeValue are not general React APIs or guaranteed fixes.

Conclusion

React onChange handlers connect user edits to component state. Read value for text and select controls, and checked for checkboxes; then render controlled controls from the updated state. Apply validation and debouncing to the needs of the form rather than as blanket rules.

FAQ

  1. What does onChange do in React? It calls a handler when a form control changes, so the component can read the new value and update its data or state.

  2. How do I handle a text input? Pass a string state value to the input’s value prop and update that state from event.target.value in onChange.

  3. How do I handle a checkbox? Control it with boolean state through checked and update that state from event.target.checked.

  4. How do I handle a select element? Set its value from state and update that state from event.target.value when the selection changes.

  5. Should I debounce every onChange handler? No. Consider debouncing when the handler starts costly work; it is not needed for every state update and does not guarantee fewer renders.

  6. Why might a programmatic value change not call my handler? Directly assigning a DOM value does not necessarily trigger React’s change handling. Update the state controlling the input or use the component’s supported interface.