<div id="app"></div>
#app {
  font-family: sans-serif;
  font-size: 0.9em;
}

label {
  display: block;
  margin-top: 1em;
  margin-bottom: 0.4em;
}

input {
  display: block;
  margin-bottom: 0.1em;
  padding: 0.6em;
  width: 200px;
  font-size: 1em;
  border: 1px solid gray;
  border-radius: 5px;
}

button {
  display: block;
  margin-top: 1.5em;
  padding: 0.6em 1em;
  border: none;
  border-radius: 5px;
  background-color: cornflowerblue;
  color: white;
  cursor: pointer;
}

button:disabled {
  opacity: 0.5;
}

small {
  color: orangered;
}
import React, { useState } from "react";
import useForm from "./hooks/useForm";

// EXAMPLE FORM SCHEMA

const initialValues = {
  username: "",
  password: ""
};

const validationSchema = {
  username: {
    match: /^(\s*).+/, // non-empty string
    error: "Required"
  },
  password: {
    match: /^(\s*).+/, // non-empty string
    error: "Required"
  }
};

// EXAMPLE FORM COMPONENT

const Login = () => {
  const [demoText, setDemoText] = useState("");
  const handleSubmit = (values) => setDemoText(JSON.stringify(values));

  // useForm HOOK creates form state & handlers
  const formState = useForm({
    initialValues,
    validationSchema,
    handleSubmit
  });

  // destructured form state
  const { values, errors, touched, valid, onChange, onSubmit } = formState;

  return (
    <div>
      <label htmlFor="username">Username</label>
      <input
        type="text"
        name="username"
        value={values.username}
        onChange={onChange}
      />
      {touched.username && <small>{errors.username}</small>}

      <label htmlFor="password">Password</label>
      <input
        type="password"
        name="password"
        value={values.password}
        onChange={onChange}
      />
      {touched.password && <small>{errors.password}</small>}

      <button disabled={!valid} onClick={onSubmit}>
        Log In
      </button>
      <br />
      <br />
      <div>{demoText}</div>
    </div>
  );
};

ReactDOM.render(<Login />, document.getElementById("app"));
View Compiled

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

  1. https://unpkg.com/react@16.7.0-alpha.0/umd/react.development.js
  2. https://unpkg.com/react-dom@16.7.0-alpha.0/umd/react-dom.development.js