How To Make Interactive ReactJS Form
Tags: react, form, beginners
Published: 2018-10-21 15:21:02

---
title: "How To Make Interactive ReactJS Form"
description: "Let's write some interactive form with React"
published: true
tags: react, form, beginner
cover_image: https://thepracticaldev.s3.amazonaws.com/i/e8xxtssiyqi7wrm5rtor.png
---

Users who visit your web application have a particular goal in mind that they want to accomplish. A form is a medium that allows your users to get in contact with you and send information, such as an order, a catalog request, or even a query, which is passed on to other processes.

A good form design that is clear and smart can help your users to achieve their goal fast. On the contrary, a badly designed form will cause confusion and even discourage users from interacting with your application.

So we agree that a good form benefits your application and make users happy. Yet implementing a good form requirements seems hard in React: dynamic forms, real-time responsive feedback, and creating a nice UX. How do we work these requirements in the land of `components`, `states` and `props`? 

The first hint that we can get is of course from React documentation about forms.

```jsx
handleChange = e => {
  this.setState({ value: e.target.value })
}

// ...

<input
  onChange={this.handleChange}
  value={this.state.value}
/>
```

This is basically the summary of React's form documentation. It simply tells you that this is how React should be used in handling users click or keystroke. React sets user's value to state and then use that state as value for the input. **The end**.

_Huh? That's it?_

Yup. As for the rest of the issues you will face when building form for an application with complex business logic.. well, they are up to you. Like doing:

1. Validation
1. Displaying errors
1. Keeping track of form fields
1. Handling submission

As it's read in the documentation, React is very unopinionated about how you might structure your project and choose your library stack. That also means it just provide the very basic necessity in making form components. `component`, `state`, `props` are just like puzzle blocks, and we need to piece them together by ourselves. 

Here's the final product you get from this tutorial:
{% codepen https://codepen.io/nathansebhastian/pen/pGoqOV default-tab=js,result %}


There are 3 basic principles you need to remember when making forms with React, they are:
1. `component` is used for rendering form elements, normally JSX elements
2. `state` is used to keep track of user's inputs
3. `props` is used for passing data into JSX elements

No matter what kind of form you are trying to create, as long as you remember these 3 basic principles, you'll be fine.

## A Basic React Form

Everything in React is a component, including a form, and React used `state` to keep track of input values. Here is an example form written in React.

```jsx
class BasicForm extends Component {
  constructor(props) {
    super(props);
    this.state = {
      name:'',
      email: '',
    };
  }

  handleNameChange = (event) => {
    this.setState({name: event.target.value});
  }

  handleEmailChange = (event) => {
    this.setState({email: event.target.value});
  }

  handleSubmit = (event) => {
    event.preventDefault();
    const { name, email } = this.state
    alert(`Your state values: \n 
            name: ${name} \n 
            email: ${email}`)
  }

  render() {
    return (
      <form onSubmit={this.handleSubmit}>
        <div className="form-group">
          <label htmlFor="name">Name</label>
          <input name="name" className="form-control" id="name" placeholder="Enter name" value={this.state.name} onChange={this.handleNameChange} />
        </div>
        <div className="form-group">
          <label htmlFor="email">Email</label>
          <input name="email" className="form-control" id="email" placeholder="Enter email" value={this.state.email} onChange={this.handleEmailChange} />
        </div>
        <button type="submit" className="btn btn-success btn-block">Submit</button>
      </form>
    );
  }
}
```

_Whoa! What does this code do?_

Don't worry, the code won't bite! Let me explain them to you now.

We'll start from `state`. A react form uses `state` as _the single source of truth_ for field values. That means every `input` element you'll have on your form `component` will take `state` value as its value.

```jsx
this.state = {
  name:'',
  email: '',
};   
```

State values are then assigned into `input` tags `value` `prop`. We also add an `onChange` `prop` that will run every time the input value is changed. Lastly, we also add `onSubmit` prop into our form component for handling submission.

```jsx
render() {
  return (
    <form onSubmit={this.handleSubmit}>
      <div className="form-group">
        <label htmlFor="name">Name</label>
        <input name="name" className="form-control" id="name" placeholder="Enter name" 
        // value and onChange prop
          value={this.state.name} 
          onChange={this.handleNameChange} />
      </div>
      <div className="form-group">
        <label htmlFor="email">Email</label>
        <input name="email" className="form-control" id="email" placeholder="Enter email" 
        // value and onChange prop
          value={this.state.email} 
          onChange={this.handleEmailChange} />
      </div>
      <button type="submit" className="btn btn-success btn-block">Submit</button>
    </form>
  );
}    
```

Next, we can add a `handleChange` method which accepts the `event` argument. This event object will hold our input name and value.

```jsx
handleNameChange = (event) => {
  this.setState({name: event.target.value});
}

handleEmailChange = (event) => {
  this.setState({email: event.target.value});
}
```

The last part of a form structure is the submit handler method. In this example, we used a `handleSubmit` method that simply call an alert box which print out our state values. 

```jsx
handleSubmit = (event) => {
  event.preventDefault();
  const { name, email } = this.state
  alert(`Your state values: \n 
          name: ${name} \n 
          email: ${email}`)
} 
```

Like a regular HTML form, this is where the saving or sending data is executed and processed. Since we're using our own JavaScript code to handle submission, we need to add `event.preventDefault()` into our submission method. This is because browser's JavaScript listener is set to listen to form submit event, which usually triggers a page reload. By using this `preventDefault`, we are telling the browser to stop doing whatever default method it does. That way the page reload will be stopped and our submission method can run.

## Making validations
The traditional approach to validate data is by submitting the form, wait for the server to finish validating, then the web page will refresh with some error message. The process takes a lot of time and cumbersome for users. 

Since React is a front-end library, it can solve this problem by building instant validation into form component. In fact, this is a common pattern in React application, and it's very awesome in my opinion. 

Since React store all form data in the state, we can use a bit of checking before `render` and display error message if data isn't valid. For an example, to validate if name length is more than 3 characters, we can use:

```jsx
render(){
  const isValidName = this.state.name.length > 3
  const isValidEmail = this.state.email.length > 3
}
```

Then to put it in context:

```jsx
// the render method

render() {
  const isValidName = this.state.name.length > 3;
  const isValidEmail = this.state.email.length > 3;
  return (
    <form onSubmit={this.handleSubmit}>
      <div className="form-group">
        <label htmlFor="name">Name</label>
        <input
          name="name"
          className={`form-control ${ isValidName? '':'is-invalid' }`}
          id="name"
          placeholder="Enter name"
          value={this.state.name}
          onChange={this.handleNameChange}
        />
        {/*feedback here*/}
      { isValidName? null: <div className='invalid-feedback'>Name must be longer than 3 characters</div> }
      </div>
      <div className="form-group">
        
        {/*after email input*/}
      { isValidEmail? null: <div className='invalid-feedback'>Email must be longer than 3 characters</div> }
      </div>
      <button type="submit" className="btn btn-success btn-block">
        Submit
      </button>
    </form>
  );
}
```

The form is validating instantly, and the error message will be gone when name is longer than 3 characters. But this validation isn't optimal because we are putting the validation logic into render method, which will turn the method into spaghetti real fast when we are validating lots of data. It also run even before we do anything with the textbox. That's not good.

## Using state for error checking
Just as we used state for data entry, we can also use state for validation. We'll add new state property in our state initialization.

```jsx
this.state = {
  name: '',
  email: '',
  nameError: '',
  emailError: ''
}
```

The `formError` state will keep our error message, and we'll use them for displaying any error message we might have. Let's put them into context by creating new validate functions:

```jsx
handleNameChange = event => {
  this.setState({ name: event.target.value }, () => {
    this.validateName();
  });
};

handleEmailChange = event => {
  this.setState({ email: event.target.value }, () => {
    this.validateEmail();
  });
};

validateName = () => {
  const { name } = this.state;
  this.setState({
    nameError:
      name.length > 3 ? null : 'Name must be longer than 3 characters'
  });
}

validateEmail = () => {
  const { email } = this.state;
  this.setState({
    emailError:
      email.length > 3 ? null : 'Email must be longer than 3 characters'
  });
}
```

With this, only when user type something into the inputs will the validation method run. Now the last thing we have to do is running validation when user clicked on a textbox, and then move to click another textbox without doing anything.

## Adding onBlur

Let's add an `onBlur` prop to our input elements.

```jsx
<input
  name='name'
  // className, id, onChange ...
  onBlur={this.validateName}
/>

<input
  name='email'
  // className, id, onChange ...
  onBlur={this.validateEmail}
/>
```

Now the validation method will run on the corresponding texbox that was "touched" by users, and then display any error message if it has. 

Here's the demo again:

{% codepen https://codepen.io/nathansebhastian/pen/pGoqOV default-tab=js,result %}

## Conclusion
Now it's time to wrap what we have learned from this simple example. Let's repeat the 3 basic principles of React form again:
1. `component` is used for rendering form elements, normally JSX elements
2. `state` is used to keep track of user's inputs
3. `props` is used for passing data into JSX elements

We have seen how this is a tried and true principle of React form. We have written a `component` that renders our JSX form. We have used `state` to keep track of `name` and `email` value, and we have used props to pass data from state values into input values, including passing a `handleChange` function into `onChange` props.

Making form in React is quite a complex task for those still unfamiliar with the way React handles data. If you need some advanced guide on React form, I recommend you to checkout Arinich's high quality [React form tutorials](https://goshakkk.name/on-forms-react/). It can help you save lots of time.

_Thanks for reading! If you love articles like this, be sure to follow me. I'll be writing more tutorials on React soon._