DEV Community

Collins Mutai
Collins Mutai

Posted on

Controlled Components - React Forms

HTML forms elements like input,textarea, and select typically re-renders every time a user submits an input. However with React, we can keep the state of the input form element in the component that renders it and only update it using useState().

With this capability in mind, we can get the value that the user inputs and use it anywhere else on our web application. This makes React state be the "single source of truth". We now can get the value of the input element by looking at our state at that current moment.

A good example would be something like a login screen, once the user submits their login credentials and is verified, the welcome screen will display a welcome text with their name on it.

To illustrate this in action we going to be using a div container with an h1 that updates it's innerText with the word "Hello" plus the name submitted on the input field when the user clicks submit.

<div className="container">
      <h1>Hello</h1>
      <input
        type="text"
        placeholder="What's your name?"
       />
      <button>Submit</button>
    </div>
Enter fullscreen mode Exit fullscreen mode

Now let's create an event handler which handles onChange events on our input field. The handleChange() will get called when a user starts typing and logs the value to the console.

function handleChange(event) {
    console.log(event.target.value); // Prints the value from the input field
  }

<div className="container">
      <h1>Hello</h1>
      <input
        onChange={handleChange}
        type="text"
        placeholder="What's your name?"
        />
      <button>Submit</button>
    </div>
Enter fullscreen mode Exit fullscreen mode

In order to control the state of our input element, we'll need to declare a useState() and set the value of the input as the state variable.

const [name, setName] = useState("");

  function handleChange(event) {
    setName(event.target.value);
    console.log(name); // Prints the value from the input field
  }
Enter fullscreen mode Exit fullscreen mode

At this point everything is working great, we now have access to our state and we know for sure what the value is for our input by checking at our state variable.

But we far from over , remember our goal was to be able to update the h1 innerText dynamically when the user submits an input. We need to find a way to keep track of our submit button so that every time the user clicks Submit, the h1 is automatically updated. Thankfully, there's an onClick event type that we can tap into.

Now we're getting close.😜 Using the onClick event, let's create another event handler that gets called whenever the submit button is clicked.

function handleClick(event) {
    console.log("I got clicked!"); //Prints I got clicked!
   }
<div className="container">
      <h1>Hello</h1>
      <input
        onChange={handleChange}
        type="text"
        placeholder="What's your name?"
        value={name}
      />
      <button onClick={handleClick}>Submit</button>
    </div>
Enter fullscreen mode Exit fullscreen mode

Since the h1 will constantly change depending on the input value, we'll need to keep track of it. And an easy way to do that is by using useState() like so.

const [headingText, setHeading] = useState("");
Enter fullscreen mode Exit fullscreen mode

Next we'll assign the h1 text as the state variable called "headingText, then set headingText as the name variable from our first useState function. In this case the name variable which corresponds to the value of the input field will now be set to the state of our h1. So technically, we are getting the value from the input field and adding it to our h1 text like so.

const [headingText, setHeading] = useState("");

function handleClick(event) {
    setHeading(name);
 }

<div className="container">
      <h1>Hello {headingText}</h1>
      <input
        onChange={handleChange}
        type="text"
        placeholder="What's your name?"
        value={name}
      />
      <button onClick={handleClick}>Submit</button>
    </div>
Enter fullscreen mode Exit fullscreen mode

Our final code snippet will look like this

import React, { useState } from "react";

function App() {
  const [name, setName] = useState("");
  const [headingText, setHeading] = useState("");

  function handleChange(event) {
    setName(event.target.value);
    console.log(name);
  }
  function handleClick(event) {
    setHeading(name);
    // event.preventDefault();
  }
  return (
    <div className="container">
      <h1>Hello {headingText}</h1>
      <input
        onChange={handleChange}
        type="text"
        placeholder="What's your name?"
        value={name}
      />
      <button onClick={handleClick}>Submit</button>
    </div>

  );
}

export default App;
Enter fullscreen mode Exit fullscreen mode

To summarize, we turned the input element into a controlled component, by making the React state be the input’s value . This allowed us to pass the value to other UI elements too like the h1.

Read more about Controlled Components 🤓 [https://reactjs.org/docs/forms.html#controlled-components]

Top comments (0)