One of the greatest features of React is the ability to create controlled forms. These allowed me to maintain and update the state of my application using the input attributes of my form. Here are some things I paid attention to when I was challenged to build a controlled form.
The Controlled Form Challenge
I can’t get enough practice with local state. Creating a form from scratch without the useForm
hook requires understanding the basics of controlled forms in React. I created a simple form that would make use of state:
I needed a single place in state to store the user’s input. The first state variable I created held the input value of the form and made use of local state inside my functional component:
Placing a callback function as the onChange
attribute in my controlled form made it possible to update the input
state variable whenever the user types. I handled local state with the React hook useState
. The initial state of input
was set to an empty string.
The value of the input attribute is set to the input
state variable. Each time the input field changes, the onChange
handler fires the callback function, setting the input equal to our event’s value. For example, here’s what logs to the console as the user types the string, “Hi, my name is Ben” (with a few typos of course).
I was challenged to store a running total of the number of characters submitted each time the user types something and clicks a submit button. This called for another state variable:
The initial state of the total
variable was passed in as 0. The form needed a button for the user to submit their string of characters and a place to show the running total of characters the user submitted.
Here came the heavy lifting. How would I convert the string of characters to a number and add to that number? The first step was setting the value of my button to the length of the input. I needed to make sure the value returned from the button-click event was an integer. By logging input.length
to the console, I could see my application counting the length of each string of characters the user typed:
I set the value attribute of my button to input.length
which was a string of the number of characters in the string. The second step was to create the button passing a handleSubmit
callback function to the onClick
handler:
The third step was to create the handelSubmit
function:
When the user clicks the button, the handleSubmit
callback function fires. Inside the function, I created a variable inputCount
that grabbed the return value of input.length
from the value attribute of my button click event and changed the string to an integer with the parseInt
function. Then I created another variable called prevTotal
that holds the current state of total
. I then updated the state of total
by passing prevTotal + inputCount
as an argument to the setTotal
callback function. To clear the input field of the form, I passed an empty string to the setInput
callback function to reset the input
state variable when the user clicks the button.
Finally, I needed a place to show the running total of characters submitted by the user:
The running total displays below the form and is updated to a new total each time the user types inside the input field and presses the “Click me!” button. Here’s the code in action:
What Did This Challenge Teach Me?
My first go at this challenge took some time. I was trying to do too many things at once without understanding the data types I was originally getting from the value attributes of my form fields. I had the right idea to set up state, but I was storing strings rather than numbers. I realized I needed to change string values to integers when I tried to add the input
state variable to my total
state variable. The result was a concatenated string and integer. Checking the input
variable’s type by logging typeOf input
to the console showed me I needed to change the value of input
and save it in a variable. I made use of parseInt
, passing it the argument event.target.value
(which was originally a number as a string). Adding this new integer variable to the previous total
state variable ensured that I added two integers together rather than a string and an integer.
Thank you for following along. I greatly appreciate your time and hope this helps!