Author avatar

Gaurav Singhal

How to Input Validation setTimeout in Reactjs

Gaurav Singhal

  • Nov 15, 2019
  • 8 Min read
  • 66 Views
  • Nov 15, 2019
  • 8 Min read
  • 66 Views
Web Development
React

Introduction

You might have had the experience of typing something into an input field and suddenly seeing errors all over the input. It's a terrible user experience—something you definitely don't want for users of your own web application.

In this guide, I'll address this prevalent issue and show you a way to delay the error messages using the setTimeout function.

An Example

For this guide, I'll create a very minimal sign-in form that will have two input fields: email and password.

Our component state would look as follows:

1
2
3
4
5
6
7
8
9
10
this.state = {
  values: {
    email: "",
    password: ""
  },
  errors: {
    email: "",
    password: ""
  }
};
jsx

We will set the error state respectively for each input field.

Validation Functions

The email and password validation functions are as follows:

1
2
3
4
5
6
7
8
9
10
11
12
validateEmail = email => {
  const re = /^(([^<>()\[\]\\.,;:\[email protected]"]+(\.[^<>()\[\]\\.,;:\[email protected]"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
  if (!re.test(String(email).toLowerCase()))
    this.setErrors({ email: "Email is invalid" });
  else this.setErrors({ email: "" });
};

validatePassword = password => {
  if (password.length < 8)
    this.setErrors({ password: "Password must have at least 8 characters" });
  else this.setErrors({ password: "" });
};
jsx

In the validateEmail() function, we use a regex to test the email entered by the user, and in the validatePassword() function we check if the password entered by the user has at least 8 characters. If the validations fail, we will set the error state for the respective field and display it.

1
2
3
4
setErrors = error =>
  this.setState({
    errors: { ...this.state.errors, ...error }
  });
jsx

Event Handlers

We will validate the input fields when the input changes or loses focus. To simplify the input handling, we will write a single onChange handler for both the inputs.

1
2
3
4
5
6
7
8
9
10
11
handleInputChange = e => {
  if (e.target.name === "email") {
    this.validateEmail(e.target.value);
  }
  if (e.target.name === "password") {
    this.validatePassword(e.target.value);
  }
  this.setState({
    values: { ...this.state.values, [e.target.name]: e.target.value }
  });
};
jsx

In the onBlur handler, we will call the validate function for the respective fields as follows:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// ...
<input
  type="email"
  name="email"
  id="email"
  value={this.state.values.email}
  onChange={this.handleInputChange}
  onBlur={e => this.validateEmail(e.target.value)}
  title="Email"
  required
/>
// ...
<input
  type="password"
  name="password"
  id="password"
  value={this.state.values.password}
  onChange={this.handleInputChange}
  onBlur={e => this.validatePassword(e.target.value)}
  title="password"
  required
/>
// ...
jsx

At this point, the validations would be done instantaneously, so we need to delay it by at least 800ms.

Delay with setTimeout

We will call the setErrors() function in the callback of the setTimeout() function.

The setTimeout() function accepts the first parameter as a function to be executed after a specific duration, and the second parameter is the time duration in milliseconds.

So our updated validation functions would be as follows:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
validateEmail = email => {
  const re = /^(([^<>()\[\]\\.,;:\[email protected]"]+(\.[^<>()\[\]\\.,;:\[email protected]"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
  if (!re.test(String(email).toLowerCase()))
    setTimeout(() => this.setErrors({ email: "Email is invalid" }), 800);
  else this.setErrors({ email: "" });
};

validatePassword = password => {
  if (password.length < 8)
    setTimeout(
      () =>
        this.setErrors({
          password: "Password must have at least 8 characters"
        }),
      800
    );
  else this.setErrors({ password: "" });
};
jsx

Complete Code

index.js file

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
import React, { Component } from "react";
import ReactDOM from "react-dom";

import "./styles.css";

class SignInForm extends Component {
  constructor(props) {
    super(props);
    this.state = {
      values: {
        email: "",
        password: ""
      },
      errors: {
        email: "",
        password: ""
      }
    };
  }

  submitForm = async e => {
    e.preventDefault();
    if (
      this.state.errors.email.length > 0 &&
      this.state.errors.password.length > 0
    )
      return false;
    console.log(this.state);
  };

  validateEmail = email => {
    const re = /^(([^<>()\[\]\\.,;:\[email protected]"]+(\.[^<>()\[\]\\.,;:\[email protected]"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
    if (!re.test(String(email).toLowerCase()))
      setTimeout(() => this.setErrors({ email: "Email is invalid" }), 800);
    else this.setErrors({ email: "" });
  };

  validatePassword = password => {
    if (password.length < 8)
      setTimeout(
        () =>
          this.setErrors({
            password: "Password must have at least 8 characters"
          }),
        800
      );
    else this.setErrors({ password: "" });
  };

  setErrors = error =>
    this.setState({
      errors: { ...this.state.errors, ...error }
    });

  handleInputChange = e => {
    if (e.target.name === "email") {
      this.validateEmail(e.target.value);
    }
    if (e.target.name === "password") {
      this.validatePassword(e.target.value);
    }
    this.setState({
      values: { ...this.state.values, [e.target.name]: e.target.value }
    });
  };

  render() {
    return (
      <div>
        <form onSubmit={this.submitForm}>
          <div className="input-group">
            <label htmlFor="email">E-mail Address</label>
            <input
              type="email"
              name="email"
              id="email"
              value={this.state.values.email}
              onChange={this.handleInputChange}
              onBlur={e => this.validateEmail(e.target.value)}
              title="Email"
              autoComplete="off"
              required
            />
            <p class="error">{this.state.errors.email}</p>
          </div>
          <div className="input-group">
            <label htmlFor="password">Password</label>
            <input
              type="password"
              name="password"
              id="password"
              value={this.state.values.password}
              onChange={this.handleInputChange}
              onBlur={e => this.validatePassword(e.target.value)}
              title="password"
              required
            />
            <p class="error">{this.state.errors.password}</p>
          </div>
          <button type="submit">Sign In</button>
        </form>
      </div>
    );
  }
}

function App() {
  return (
    <div className="App">
      <h1>Sign In To Your Account</h1>
      <SignInForm />
    </div>
  );
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
jsx

styles.css

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
.App {
  font-family: sans-serif;
}

.input-group {
  margin-bottom: 10px;
}

.input-group label {
  display: block;
  margin-bottom: 5px;
}

button {
  border: none;
  padding: 8px 24px;
}

.message {
  margin-top: 20px;
  font-weight: 600;
}

.error {
  color: red;
  font-size: 14px;
}
css

Conclusion

In this guide, we looked at how we can tackle a common UX issue on input validations to enhance the usability of forms in web applications.

That's it from this guide. I hope you liked it. For more other tips, refer to my other guides on React.

0