DEV Community

loading...
Cover image for TIL - React Forms - controlled & uncontrolled components

TIL - React Forms - controlled & uncontrolled components

Anne Quinkenstein
Quality Engineer & Junior Frontend Developer
Updated on ・2 min read

Summery

  • A controlled component is a component where React is in control and is the single source of truth for the form data.
  • An uncontrolled component is where your form data is handled by the DOM, instead of inside your React component.

HTML Forms

When submitting a form, is made up of key-value pairs:

<form>
 <label for='id'> </label>
 <input id='id' type='text' name='key' value='value'>
</form>
Enter fullscreen mode Exit fullscreen mode

In HTML, the user can modify the field, regardless of whether the attribute value is set or not.

With React, the field can only be modified if no attribute value is given to it.

Uncontrolled field

-> no value has been put on the input-field

<form<
    <label htmlFor="character">Character:</label>
    <input
        id="character"
        name="character"
        type="text"
        onChange={(event) => {
           const input = event.target;
           console.log('NAME:', input.name, 'VALUE:',      
            input.value);
          }}
    />
 </form>
Enter fullscreen mode Exit fullscreen mode
  • use htmlFor instead of for on the <label> for is a reserved keyword in JavaScript.
  • the use of onChange which allows to detect user input. It's the event listener associated with onChange which is responsible for the display you see in the console.
  • event.target in the event listener of onChange is the element of the page on which the event occurred: the <input> field.
  • The console displays the input's attributes: name (which does not change) and value (which varies as you type).
  • Because there's no value attribute set on the character field, the value displayed in the field the one entered by the user.
 const handleSubmit = (event) => {
    event.preventDefault();
    const firstName = event.target.firstName.value;
    const lastName = event.target.lastName.value;
    // Here we do something with form data
    console.log(firstName, lastName)
  }

 <form onSubmit={handleSubmit}>
        <label>
          Name:
          <input name="firstName" type="text" />
        </label>
        <label>
          Surname:
          <input name="lastName" type="text" />
        </label>
        <input type="submit" value="Submit" />
  </form>
Enter fullscreen mode Exit fullscreen mode

The uncontrolled component above poses this problem: the value is not stored at the state level.

Controlled field

An <input> field is said to be controlled when the <value> of its value attribute is provided by the component that displays it: usually, this value comes from the state of the component.
Different from HTML: React controls the field's value via the value attribute.

  1. You'll have to change the name of the key to be initialized in the state.
  2. In the render instead of a hardcoded value, set the input's value attribute using the value contained in the state.
  3. Change the Value in the State:
const EssayForm = () => {

const [ value, setValue ] = useState(''); 

const handleChange =(event) => { setValue({event.target.value});  }
const handleSubmit= (event) => {
 alert('An essay was submitted: ' + value);
 event.preventDefault();
 }

  render() {
    return (
      <form onSubmit={handleSubmit}>
        <label>
          Essay:
          <textarea value={value} onChange={handleChange} />             
        </label>
        <input type="submit" value="Submit" />
      </form>
    );
  }
}
Enter fullscreen mode Exit fullscreen mode

first steps

Discussion (0)