React login form validation

React login form validation, using Babel + JSX

by Allie Yu

HTML

<div id="app"></div>

<script src="https://fb.me/react-15.1.0.js"></script>
<script src="https://fb.me/react-dom-15.1.0.js"></script>

<!-- this is via: https://goshakkk.name/instant-form-fields-validation-react/ -->

CSS

* {
  box-sizing: border-box;
}

body {
  padding-top: 0;
  font-family: Helvetica Neue, Helvetica;
  background: azure;
}

h3 {
  font-size: 18px;
  margin-top: 20px;
  margin-bottom: 5px;
}

form {
  padding: 0 40px;
}

form input {
  display: block;
  width: 100%;
  font-size: 20px;
  padding: 5px 10px;
  margin: 10px 0;
  border-radius: 5px;
  border: 1px solid #ddd;
}

form input.error {
  border-color: red;
}

form span.error {
  color: red;
}

.hidden {
  display: none;
}

form button {
  display: block;
  width: 100%;
  appearance: none;
  border-radius: 5px;
  background-color: #84c00c;
  color: #fff;
  border: none;
  font-size: 16px;
  height: 40px;
  margin-top: 30px;
}

form button:hover {
  background-color: #669509;
}

form button:disabled {
  background-color: #dbf99f;
  color: #333;
}

Babel + JSX

function validate(email, username, password) {
  // true means invalid, so our conditions got reversed
  return {
    email: email.length === 0, //true if email is empty
    username: username.length === 0, //true if username is empty
    password: password.length === 0, //true if password is empty
  };
}

class SignUpForm extends React.Component {
  constructor() {
    super();
    this.state = {
      email: '',
      username: '',
      password: '',
      
      touched: {
        email: false,
        username: false,
        password: false,
      },
    };
  }
  
  handleEmailChange = (evt) => {
    this.setState({ email: evt.target.value });
  }
  
  handleUsernameChange = (evt) => {
    this.setState({ username: evt.target.value });
  }
  
  handlePasswordChange = (evt) => {
    this.setState({ password: evt.target.value });
  }
  
  handleBlur = (field) => (evt) => {
    this.setState({
      touched: { ...this.state.touched, [field]: true },
    });
  }
  
  handleSubmit = (evt) => {
    if (!this.canBeSubmitted()) {
      evt.preventDefault();
      return;
    }
    const { email, username, password } = this.state;
    alert(`Signed up with email: ${email} password: ${password}`);
  }
  
  canBeSubmitted() {
    const errors = validate(this.state.email, this.state.username, this.state.password);
    const isDisabled = Object.keys(errors).some(x => errors[x]);
    return !isDisabled;
  }
  
  render() {
    const errors = validate(this.state.email, this.state.username, this.state.password);
    const isDisabled = Object.keys(errors).some(x => errors[x]);
    
    const shouldMarkError = (field) => {
      const hasError = errors[field];
      const shouldShow = this.state.touched[field];
      
      return hasError ? shouldShow : false;
    };
    
    return (
      <form onSubmit={this.handleSubmit}>
        <input
          className={shouldMarkError('email') ? "error" : ""}
          type="text"
          placeholder="Enter email"
         ...