Changing of Values

Learn how states are modified and controlled in various HTML elements.

If a value is modified, as is the case with text inputs and radio buttons, the corresponding React state is set to the value provided by the user, triggered by the onChange event. Controlled components now mandate the following procedure:

  1. When the user inputs text, the value changes.
  2. The onChange event is triggered and processed by the event handler.
  3. The event handler sets the state using the new value.
  4. React re-renders the user interface and sets this.state to the new value.
  5. The user sees their newly provided value on the screen.

This looks normal to the user, and they will not notice that the form works differently behind the scenes and does not reflect usual browser behavior. React fully takes care of the logic in the background and paints a new frame in the user interface.

Changing states

Checkboxes

Checkboxes (<input type="checkbox" />) work similarly, but their value will remain the same. Checkboxes change their state rather than their value by providing the boolean true or false in its checked property. If React controls the checked property, the form field is said to be controlled. One can check whether the checkbox is activated (true) or not (false) by inspecting e.target.checked in the event handler, which passes this information to React state. React then takes care of the re-render and shows the status of the checkbox to the user.

Radio buttons

Radio buttons on the other hand, are a kind of a hybrid element. Similar to checkboxes, radio buttons are seen as controlled if React manages their checked attribute. However, there are often multiple radio buttons containing the same name but different values within the same document. It would not make sense to set the values of these names to either true or false as we are interested in the actual value of the selected radio button. Thus, the value of the radio button is written into the state. We can check whether the selected value in the state is the same as the value of the field with:

checked={this.state.radio === "1"}

We set checked to true in this case if the value of the radio button radio is equal to 1.

Changing state with simple or multiple selects

Let’s start with a simple use case. A simple <select> list modifies its value just like a text field, then triggers a re-render and finally shows the selected value in the freshly painted user interface. Multiple selects form an exception though.

Other than their counterparts, a simple select list or a simple text input, multiple select lists do not expect a string value but an array of strings. Annoyingly, we have to construct this array ourselves as e.target.value only ever contains a single value, even if multiple options are possible. The e.target.selectedOptions property, an object of type HTMLCollection, can help us and contains a list of <option> elements which are currently selected. This object can easily be transformed into an array using the static array method Array.from() added in ES2015. Using Array.map(), we can further iterate over this array and return a new array containing all the relevant values:

Array.from(selectedOptions).map((option) => option.value);

The newly created array is then written into the state as a new value. But before that, we check using e.target.multiple whether we are actually dealing with a <select> with multiple choices as it is only this <select> which expects an array as a value.

Alternatively, we could have passed the changeValue method to the simple select and the changeSelect method to the select with multiple choices. Because each select would have received its own event handler, we could have avoided the additional check of checking for a multiple select. However, following the procedure shown above will make your code more resilient to change requests as the type can be easily changed in the future. In the end, it is up to you though.

Get hands-on with 1200+ tech skills courses.