DEV Community

Jacob Colborn
Jacob Colborn

Posted on

How to handle inputs with React

When working on my latest demo application, I ran into a problem with React; I wanted to create form. The problem with this simple task is I didn't want any backend or API to handle the form, instead, I wanted it to work within React. I found a lot of things that were complex, but I think I created a system that works.

Gathering the data

The first thing I did was create the "form." To do this, I created a group of inputs within a <div>. The input would look like this:

<input 
    class="rounded" 
    id="gametitle" type="text" 
    placeholder="Game Title" 
    onChange={this.props.onChange} 
    value="{this.props.gameTitle}"
/>

The most important part of this is the onChange and the value properties. The value property will read the state that is being generated by onChange. onChange is a method passed into the React class with a prop called onChange. These work together to create an input that can be used to gather the data and then cleared.

onChange = event => {
    switch (event.target.id) {
        case "gametitle":
            this.setState({ gameTitle: event.target.value });
            break;
        ...
    }
}

The method will collect the event generated. It will then use the input's id value to match the correct case. From here, it gathers the current value of the input with event.target.value and sets the state to be that value. gameTitle was defined in the constructor of the React class, along with the other bits of state, before being used.

Handling the data

After gathering all 4 inputs, I then needed to collect the data and clear the inputs for the next round of data. For this, a button was in order. The final input was the button:

<input
    class="rounded"
    id="enter"
    type="submit"
    text="Add"
    onClick={this.props.onSubmit}
/>

The button is a bit different. It uses the onClick value to watch for user interaction (in this case when the user clicks the button area). The method was passed into the class via a prop (as was onChange) called onSubmit.

onSubmit = event => {
    if (
      this.state.gameTitle === undefined
    ) {
      alert("Error: undefined element");
    } else {
      if (this.state.games == null) {
        this.setState({
          games: [
            {
              gameTitle: this.state.gameTitle,
              date: this.state.date,
              digital: this.state.digital,
              platform: this.state.platform
            }
          ]
        });
      } else {
        this.setState({
          games: [
            ...this.state.games,
            {
              gameTitle: this.state.gameTitle,
              date: this.state.date,
              digital: this.state.digital,
              platform: this.state.platform
            }
          ]
        });
      }
    }

    this.setState({
      gameTitle: "",
      date: todayDate,
      digital: false,
      platform: ""
    });
}

There are a few things going on here, so I will start from the top. The first thing to do is to make sure that the user has entered all of the required data. To do this, I check the four input's state value to see if it is null. From there, I need to see if the games: [] array already has a value in it. If there is no value, I enter the four input's values as the first object. When a previous value exists, I reset the state to be the current value of state and then add the data to the rear. The array is modified with the spread syntax, games: [...this.state.games], which references the entire array and allows the current state to be appended. This will keep the state immutable. The final part sets the state of the inputs back to blanks since the inputs are using the state as their value.

You can see all of the code for this at GitLab.

Top comments (2)

Collapse
 
briang123 profile image
Brian Gaines • Edited

Keep up the work! You may want to consider revising your onChange event to eliminate those switch case statements by structuring your input onChange event handler to point to a function that takes in the event target. This will allow your onChange to be more generic. I've also included an updateState function, as well here. As far as your setState, you might be able to improve that by using destructuring.

updateState = (key, value) => this.setState((prevState, props) => (prevState[key] = value));

onChange = e => this.updateState([e.target.name], e.target.value);

input type="text" name="mycontrol" value={this.state.mycontrol} onChange={this.onChange}

Collapse
 
jakesweb profile image
Jacob Colborn

Good tips. I am going to look into those. I was trying to think of a way to make the onChange more generic but could not come up with anything. Your way is very clear.