React Forms

Emil Andreasyan
5 min readOct 4, 2020

Forms both in React and in other programming languages are one of the most often used attributes that can either bring to better user experience or dissatisfaction whenever the data cannot be submitted. Either you want to sign in or sign up, they are the essentials part of most web applications. But let’s stay positive and build a form that will not eventually break and will work seamlessly, the way it’s supposed to. For this reason, we’ll build React-based and backed forms that are relatively easy to build and require full implementation of one of the main React properties called state while, as you might know, stateare the data that intrinsic to the component and can dynamically change on every interaction. We will also cover in this article two most used events such as onChange and onClick.

As an instance, we can cover the registration form, one of the most used forms out there. In general, what commonalities all the registration forms have? First of all, there are input fields where the user types something (usually, name, email, and that kind of stuff). Then, when user types, React somehow understands, reacts, and stores that specific data. After that, we click the submit button. When that happens, it triggers a “two-sided conversation” before front and back ends, where we send that specific data that the user typed in. Back-end either responses with 200 status (ok), or shoots an error if the data is invalid, the specified path is inaccurate, etc. First things first, let’s start with a single form that doesn’t do much (except looking cool) and add some functionality and complexity as it evolves.

import React, { Component } from 'react';export default class Registration extends Component {
render() {
return (
<>
<form className="form-control">
<input type="text" name="name"/>
<input type="email" name="email" required/>
<input type="password" name="password"/>
<button type="submit">Register</button>
</form>
</>
)
}
}

This is a classical form written by JSX. We have a form opening and closing tags, input fields with different types, submit button (which doesn’t do anything right now). This is what the user sees and instinctively tries to submit the filled data. Let’s help the user to have the best experience by adding some functionality! First of all, we have to deal with statewhile as you know, stateare responsible for dynamic data, such as forms, increment, etc.

export default class Registration extends Component {
state = {
name: "",
email: "",
password: "",
}
}

As you notice, stateis an object with key-value pairs, where the keys should exactly match with nameparameter of the form. For instance, if in the form we have name=”password”, then in statewe must have the matching passwordkey. Another thing to mention here is that valuerepresents the initial value, in our case an empty string to start with (or 0 if dealing with a counter). That’s good, but how do we connect them together and change the state? Don’t be hasty, Smeagol! We can all agree that whenever we type, we want the input fields to change, so, let’s change it programmatically by writing onChange eventListener!

export default class Registration extends Component { state = {
name: "",
email: "",
password: "",
}
handeChange = event => {
const {name, value} = event.target;
this.setState({[name]: value})
}
render() {
return (
<>
<form className="form-control">
<input type="text" name="name" value={this.state.name}
onChange={this.handeChange}/>
<input type="email" name="email" value={this.state.email}
onChange={this.handeChange} required/>
<input type="password" name="password" value={this.state.password}
onChange={this.handeChange}/>
<button type="submit">Register</button>
</form>
</>
)
}
}

Let’s take a moment and look at what just was added and how it will now function. First of all, the valueattribute in the input field appeared. value={this.state.email}represents what in the current moment the value of state. onChangeis responsible for every keystroke we type in the field. So, whenever we do so, we want to run a particular function conventionally named handleChange. We access this function bythis keyword. Thus, we have onChange={this.handleChange}. As we look just above our form we’ll notice the handleChangefunction. In this simple yet powerful function, first, we designate the roles by creating variables (const name = event.target.name, const value = event.target.value, or simply and nicely restructuring them as const { name, value }= event.target so we can type shorter syntax afterward). A line below is where all the magic happens when we invoke another React-specific method called this.setState. If the stateis initial value, setStateis what we want this value to become. It returns an object when we event.target.nameto event.target.value (or simply [name]: value). For instance, if initially name=”email” represents an empty string, we now set that nameto whatever the value we typed in by implementing setStatemethod.

So by far, we have done a lot of work but there is one more step that need to be done for our form to be fully capable of managing data. We need to submit these values to the back-end. We can do it by using onSubmit eventListenerand handleSubmitmethod.

...
<form className="form-control" onSubmit={this.handleSubmit}>
...

Just a few lines above we can write our method required for all the forms whenever we need to send and get back data from the server-side.

...
handleSubmit = event => {
const {name, email, password} = this.state
event.preventDefault();
fetch("http://localhost:3000/registration", {
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json'
},
method: 'POST',
body: JSON.stringify({name, email, password})
})
.then(resp => resp.json())
.then(data => this.setState({name: data.name, email: data.email, password: data.password}))
.catch(err => console.log(err))
}
<form className="form-control" onSubmit={this.handleSubmit}>
...

Without explicitly describing fetchmethod, we can see what it actually does. We specify the address of the server-side where the data must be sent, we say to the server that this data type is json. We explicitly what type of HTTP request it is (POST), we convert the json data to a string by using JSON.stringify method. Then we receive a promise that some type of data will be sent back, then we receive the data itself and update our stateaccording to the received data by using setStatemethod.

Conclusion

Forms are a great example to see the power of React in action. They represent one of the most common experiences the user encounters throughout the webpages. After spending some time required for initial setup and elaborating every detail, React forms start to perform all the magic and seamless communication with the back-end where we can decide what to do with the received data, how to update state on the front-end, persist the data in the server-side database, or not. But that’s a story for another article.

--

--