REACT-ing gracefully with controlled components

I'm just a girl, searching for the single source of truth.

What are controlled components, and why? React form elements are similar to regular HTML forms in setup, but they are able to perform some extras for us when we use State. Unlike HTML forms where elements would typically maintain and update their own state based on user input, React uses mutable state that is kept in the state variable and is updated with setState(). But, using these methods together, is what brings us to that glorious single source of truth. When we tie the value of the element form to the state controlled by React, we form a controlled component. A controlled component derives its input values from state.

We are able to use state with HTML elements like <input />, <select />, and <textarea /> when we pass it a value prop of the current state.

Let's start with a quick form setup with two inputs below.

import React, { useState } from "react";

function myControlledForm() {
  const [name, setName] = useState("");
  const [favoriteColor, setFavoriteColor] = useState("");

  return (
    <form>
      <input type="text" value={name} />
      <input type="text" value={favoriteColor} />
      <button type="submit">Submit</button>
    </form>
  );
}

export default Form;

Here we have set up a state variable name and it's setter function setName. It has an initial state declared as an empty string, but which will be updated as soon as, and every time setName is called.

In the form elements themselves, we are tying the first input to the name state and the second input to the favorite color state. But we still need to wire up the onChange event listener to an event handler callback function.

<input type="text" onChange={handleNameChange} value={firstName} />
<input type="text" onChange={handleColorChange} value={lastName} />

By adding this event listener to an input as a prop, it will listen for change events. Each change, a callback function will fire to capture the user input value, and update its state variable.

It is typical naming convention for your callback function to be named corresponding to the state variable it is handling the change for.

function handleNameChange(event) {
  setFirstName(event.target.value);
}

function handleColorChange(event) {
  setLastName(event.target.value);
}

These functions use the event.target.value, which is being provided by the inputs onChange event handler to update the state variable using its corresponding setState function, which we declared above. When we update the state, we cause a re-render, and a cycle is completed.

Why use controlled components though? Here are some key benefits:

  • Controlled inputs allow for more control over inputs and data.
  • When we use state to store form input values, we can then share state with other components, and make changes in our applications. All components using this value will always have access to the exact same, current value.
  • When we set up a form component, we can set the state in its parent component, and pass down variables and event handlers as props. This setup can allow for more dynamic changes in other parts of the application.
  • We can also send the form data to other parts of our application for storage or for posting to a database.
  • Controlled inputs can be validated.

There are some really cool implementations of controlled inputs; I like to think about filtering search results as you type. Just the same way we controlled this simple input form with onChange and a callback, we can use these search values derived from state in a more scalable, expansive application to search and filter through all sorts of data.

22