React useFormState

UseFormState is a flexible React Hook that manages the state of a web form.

This library is under development. A NPM module will be made available when it is ready.

Form:
Email Address:

New password:

Repeat password:

Optional input:

Form state:

formIsValid: false

hasSubmitted: false

submitSuccess: false

Input Values:
  • email:
  • password:
  • passwordRepeat:
  • optionalInput:
Input Validities:
  • email: false
  • password: false
  • passwordRepeat: true
  • optionalInput: true
Input Error Message:
  • email: Please enter a valid email address.
  • password: Please enter a password of 5 characters or more.
  • passwordRepeat:
  • optionalInput:
updatedSinceLastSubmit:
  • email: false
  • password: false
  • passwordRepeat: false
  • optionalInput: false
jsx

const initialValues = {
  email: '',
  password: '',
  passwordRepeat: '',
  optionalInput: '',
};

const validationRules = (state) => {
  return {
    email: [
      {
        rule: 'hasMinLength',
        param: 1,
        errorMsg: 'Please enter a valid email address.',
      },
      {
        rule: 'isEmail',
        errorMsg: 'Please enter a valid email address.',
      },
    ],
    password: [
      {
        rule: 'hasMinLength',
        param: 5,
        errorMsg: 'Please enter a password of 5 characters or more.',
      },
    ],
    passwordRepeat: [
      {
        rule: 'isEqualTo',
        param: state.password,
        errorMsg: 'Password does not match.',
      },
    ],
  };
};

// This function mocks a server request by returning a promise that resolves itself
// after a specified time.
const sleep = (milliseconds: number) => {
  return new Promise((resolve) => setTimeout(resolve, milliseconds));
};

export const UseFormStateExample = ({ style }) => {
  const formOnSubmit = useCallback(({ inputValues }) => {
    const asyncLogin = async () => {
      await sleep(1000);
      return true;
    };

    return asyncLogin();
  }, []);

  const { formState, handleChange, handleSubmit } = useFormState(
    initialValues,
    formOnSubmit,
    validationRules
  );
  

  const handleChangeEmail = useCallback(
    (event) => handleChange('email', event.target.value),
    [handleChange]
  );

  const handleChangePassword = useCallback(
    (event) => handleChange('password', event.target.value),
    [handleChange]
  );

  const handleChangePasswordRepeat = useCallback(
    (event) => handleChange('passwordRepeat', event.target.value),
    [handleChange]
  );

  const handleChangeOptionalInput = useCallback(
    (event) => handleChange('optionalInput', event.target.value),
    [handleChange]
  );

  return (
    <div style={{ display: 'flex', ...style }}>
      <div style={{ padding: '24px', width: '50%' }}>
        <h5>Form:</h5>
        <h6>Email Address:</h6>
        <input
          onChange={handleChangeEmail}
          value={formState.inputValues.email}
          aria-label="email-input"
        />
        <p>{formState.hasSubmitted && formState.inputErrorMessages.email[0]}</p>
        <h6>New password:</h6>
        <input
          onChange={handleChangePassword}
          value={formState.inputValues.password}
          aria-label="password-input"
        />
        <p>
          {formState.hasSubmitted && formState.inputErrorMessages.password[0]}
        </p>
        <h6>Repeat password:</h6>
        <input
          onChange={handleChangePasswordRepeat}
          value={formState.inputValues.passwordRepeat}
          aria-label="password-repeat-input"
        />
        <p>
          {formState.hasSubmitted &&
            formState.inputErrorMessages.passwordRepeat[0]}
        </p>
        <h6>Optional input:</h6>
        <input
          onChange={handleChangeOptionalInput}
          value={formState.inputValues.optionalInput}
          aria-label="password-optional-input"
        />
        <p>
          {formState.hasSubmitted &&
            formState.inputErrorMessages.optionalInput[0]}
        </p>
        <button onClick={handleSubmit}>Submit</button>
        {formState.hasSubmitted && <p>Has submitted!</p>}
        {formState.submitSuccess && <p>Submit success!</p>}
      </div>
    )
  }