Hello Sunil
mastering-controlled-components-react-feature-image

Mastering Controlled Components in React: A Step-by-Step Guide with Examples

In React, Controlled Components are components where form data is handled by the React component itself, keeping the UI and state in sync. The form element’s value is linked to a piece of React state, which allows you to control the input directly through React.

Also Read: Controlled vs. Uncontrolled Components in React

In this guide, we’ll cover how to handle various input types as Controlled Components:

  • Text Input
  • Email Input
  • Password Input
  • Checkboxes
  • Radio Buttons
  • Dropdowns
  • Multiple form fields

Let’s dive in!

In this example, we create a controlled text input where the input’s value is managed by a piece of React state.

TextInput.js

"use client"
import React, { useState } from 'react';

const TextInput = () => {
	const [text, setText] = useState('');

	const handleChange = (e) => {
    setText(e.target.value);
  };
	return (
		<div>
      <label>Text Input:</label>
      <input type="text" value={text} onChange={handleChange} />
      <p>Entered Text: {text}</p>
    </div>
	)
}

export default TextInput

Explanation:

  • text is a state variable that holds the current value of the input.
  • handleChange updates text whenever the user types. e.target.value captures the latest input value.
  • value={text} binds the input value to the text state, making it controlled by React.

Output:

handling-text-input-react-controlled-components

This example manages an email input field in a similar way, demonstrating basic form handling for emails.

EmailInput.js

"use client"
import React,{useState} from 'react'

const EmailInput = () => {
	const [email, setEmail] = useState('');

  const handleChange = (e) => {
    setEmail(e.target.value);
  };
	return (
		<div>
		<label>Email:</label>
		<input type="email" value={email} onChange={handleChange} />
		<p>Entered Email: {email}</p>
	</div>
	)
}

export default EmailInput

Explanation:

  • The email state variable holds the email input’s current value.
  • Every change to the input updates email through handleChange.
  • The type="email" attribute hints to the browser that this field is for an email, providing built-in validation on submission.

Output:

handling-email-input-react-controlled-components

In this password input example, we keep the password hidden but store it in state.

PasswordInput.js

"use client"
import React,{useState} from 'react'

const PasswordInput = () => {
	const [password, setPassword] = useState('');

  const handleChange = (e) => {
    setPassword(e.target.value);
  };
	return (
		<div>
		<label>Password:</label>
		<input type="password" value={password} onChange={handleChange} />
	</div>
	)
}

export default PasswordInput

Explanation:

  • password holds the entered password value.
  • type="password" ensures the input hides the characters.
  • React manages the password state as the user types, keeping it secure and accessible for further processing.

Checkboxes use a boolean (true/false) state to indicate whether they’re checked.

CheckboxInput.js

const CheckboxInput = () => {
	const [isChecked, setIsChecked] = useState(false);

  const handleChange = (e) => {
    setIsChecked(e.target.checked);
  };
	return (
		<div>
      <label>
        <input type="checkbox" checked={isChecked} onChange={handleChange} />
        Accept Terms
      </label>
      <p>Checkbox is {isChecked ? 'Checked' : 'Unchecked'}</p>
    </div>
	)
}

export default CheckboxInput

Explanation:

  • isChecked stores whether the checkbox is checked (true or false).
  • e.target.checked returns a boolean based on the checkbox’s state, updating isChecked as the user interacts.
  • checked={isChecked} keeps the checkbox’s status in sync with the state.

Output:

handling-checkboxes-input-react-controlled-components

Radio buttons are grouped by name and handle a single, specific selection.

RadioButtons.js

"use client"
import React,{useState} from 'react'

const RadioButtons = () => {
	const [selectedOption, setSelectedOption] = useState('');

  const handleChange = (e) => {
    setSelectedOption(e.target.value);
  };
	return (
		<div>
      <label>
        <input type="radio" value="option1" checked={selectedOption === 'option1'} onChange={handleChange} />
        Option 1
      </label>
      <label>
        <input type="radio" value="option2" checked={selectedOption === 'option2'} onChange={handleChange} />
        Option 2
      </label>
      <p>Selected Option: {selectedOption}</p>
    </div>
	)
}

export default RadioButtons

Explanation:

  • selectedOption holds the currently selected radio button’s value.
  • Each radio button has a unique value and checks if it matches selectedOption.
  • When the user selects an option, handleChange updates selectedOption, making only one option selectable at a time.

Output:

handling-radio-button-react-controlled-components

Dropdowns allow a single selection from multiple options.

Dropdown.js

"use client"
import React,{useState} from 'react'

const Dropdown = () => {
	const [selectedValue, setSelectedValue] = useState('');

	const handleChange = (e) => {
    setSelectedValue(e.target.value);
  };
	return (
		<div>
      <label>Choose an option:</label>
      <select value={selectedValue} onChange={handleChange}>
        <option value="">Select</option>
        <option value="option1">Option 1</option>
        <option value="option2">Option 2</option>
        <option value="option3">Option 3</option>
      </select>
      <p>Selected: {selectedValue}</p>
    </div>
	)
}

export default Dropdown

Explanation:

  • selectedValue is the current value of the dropdown.
  • value={selectedValue} makes the dropdown controlled by linking it to selectedValue.
  • handleChange updates selectedValue each time the user selects an option, keeping the dropdown’s selection consistent.

Output:

handling-dropdowns-controlled-components

For a form with multiple inputs, we can manage all fields in a single state object.

MultiFieldForm.js

"use client"
import React,{useState} from 'react'

const MultiFieldForm = () => {
	const [formValues, setFormValues] = useState({
    name: '',
    email: '',
    password: '',
  });

  const handleChange = (e) => {
    const { name, value } = e.target;
    setFormValues((prevValues) => ({
      ...prevValues,
      [name]: value,
    }));
  };
	return (
		<div>
      <label>Name:</label>
      <input type="text" name="name" value={formValues.name} onChange={handleChange} />
      <label>Email:</label>
      <input type="email" name="email" value={formValues.email} onChange={handleChange} />
      <label>Password:</label>
      <input type="password" name="password" value={formValues.password} onChange={handleChange} />
      <p>Form Data: {JSON.stringify(formValues)}</p>
    </div>
	)
}

export default MultiFieldForm

Explanation:

  • formValues is an object holding multiple field values.
  • name attributes in the inputs correspond to keys in formValues.
  • handleChange updates the specific field in formValues by matching name to a property and updating only that property with value, keeping all inputs synchronized in one state.

React’s controlled components give you precise control over each form element, making it easy to manage, validate, and manipulate user inputs.

By linking input values directly to React state, you maintain a predictable and maintainable form experience. This approach is especially powerful in large applications where form data integrity is essential.

How useful was this post?

Click on a star to rate it!

Average rating 0 / 5. Vote count: 0

No votes so far! Be the first to rate this post.

We are sorry that this post was not useful for you!

Let us improve this post!

Tell us how we can improve this post?

Similar articles you may like

Sunil Pradhan

Hi there 👋 I am a front-end developer passionate about cutting-edge, semantic, pixel-perfect design. Writing helps me to understand things better.

Add comment

Stay Updated

Want to be notified when our article is published? Enter your email address below to be the first to know.

Sunil Pradhan

Hi there 👋 I am a front-end developer passionate about cutting-edge, semantic, pixel-perfect design. Writing helps me to understand things better.