npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

react-use-form-hooks

v0.4.2

Published

React hooks for managing form state.

Readme

react-use-form-hooks

React hooks for managing form state. Uses React Hooks API to manage common form elements state. The hooks are meant to be generic and usefull.

Requires react@^16.8.0 react-dom@^16.8.0 as peer dependencies.

Features

  • Keeps field value state
  • Keeps field touched state
  • Keeps field validation state
  • Executes validation and exposes validation errors
  • Will support async validation (TODO)

Installation

npm

npm i --save react-use-form-hooks

yarn

yarn add react-use-form-hooks

Usage

Live demo

Example:

import React from 'react';
import { useFormField, useFormWithFields } from 'react-use-form-hooks';

export default () => {
  const fieldOne = useFormField({
    initialValue: '',
    isRequired: true,
    validate: doValidationSomehow
  });

  const fieldTwo = useFormField();

  const form = useFormWithFields({
    onSubmit: doSomethingWithAcceptableFormData,
    fields: [fieldOne, fieldTwo]
  });

  return (
    <form onSubmit={form.handleSubmit}>
      <MyInput
        label="Field One"
        type="text"
        value={fieldOne.value}
        required={fieldOne.isRequired}
        onChange={fieldOne.handleChange}
        isValid={fieldOne.isValid}
        isTouched={fieldOne.isTouched}
        validationErrors={fieldOne.validationErrors}
        successfulValidations={fieldOne.successfulValidations}
      />
      <MyInput
        label="Field Two"
        type="can be anything really"
        value={fieldTwo.value}
        required={fieldTwo.isRequired}
        onChange={fieldTwo.handleChange}
        isValid={fieldTwo.isValid}
        isTouched={fieldTwo.isTouched}
        validationErrors={fieldTwo.validationErrors}
        successfulValidations={fieldTwo.successfulValidations}
      />
      <button type="submit" disabled={!form.isSubmittable}>
        Submit
      </button>
    </form>
  );
}

API

The module exports two hooks: useFormField and useFormWithFields.

useFormField

const field = useFormField(params);

Returns object with following fields:

{
  isEmpty, // boolean; indicates whether field value is empty
  isRequired, // boolean
  isTouched, // boolean; indicates whether field value has been changed
  isValid, // boolean; indicates whether field value is valid
  isAcceptable, // boolean; indicates whether field is known to be OK to be used in form data submission
  handleChange, // function; should be called on controlled input change if it should be validated immediately
  handleChangeValueOnly, // function; should be called on controlled input change if it should NOT be validated immediately. Field will be validated on blur or submission attempt instead
  handleReset, // function; reset field to initial state
  handleClear, // function; clear field value
  handleSubmitAttempt, // function: Called by useFormWithFields hook. May be called manually on form submit attempt if useFormWithFields is not used
  successfulValidations, // array of successful validations results
  validationErrors, // array of failed validation results / validation error messages
  value //any; field value
}

Parameters

{
  accessor, // function or string, optional
  adapter, // function, optional
  emptyValue, // any, optional
  initialValue, // any, optional, default is empty string
  isRequired, // boolean, optional, default is false
  validate, // function, optional
  validateRequired // function, optional
}
accessor

Optional. Used to extract field value out of object passed as a parameter to handleChange and handleChangeValueOnly handlers.

If accessor is a string, it is used as a path to object's value.

If accessor is a function it is expected to return the new value.

Note: if no acessor is provided, the hook will first attempt to treat parameter as event and resolve it's 'target.value' path. In case if 'target.value' path returns undefined, the raw param will used as value.

adapter

Optional. Used to supplement field values. For example, to produce a shape that can be fed to bootstap components. The function only needs to return the new fields.

emptyValue

Optional. Value that will be set on field clear with handleClear.

initialValue

Optional. Defaults to empty string. Initial value. Will also be set on field reset with handleReset.

isRequired

Optional. If true, field will be treated as not OK for submission when empty.

validate

Optional. Function that is used to validation the field.

More on validation here

validateRequired

Optional. Function that is used to check if field is empty. Should return error message or any truthy value if field is empty and a falsy value otherwise. Defaults to a function that returns truthy for undefined, null, '' and [] values.

useFormWithFields

const field1 = useFormField(params);
const field2 = useFormField(params);
const form = useFormWithFields({
    onSubmit: submitValidFormDataSomehow,
    fields: [field1, field2]
  });

Returns object with following fields:

{
  isSubmittable, // boolean; indicates whether all form fields are OK
  isSubmitAttempted, // boolean; indicates whether handleSubmit has been called at least once
  handleSubmit // function to be called on form submission attempt
}

Parameters

{
  onSubmit, // function; called on submit attempt if all fields are OK
  onFailedSubmit, // function; called on submit attempt if at least one field is not OK
  fields // array of return values of useFormField hooks
}
onSubmit

Optional. If supplied, it will be called with the param (usually event) passed to the handleSubmit handler only if all fields listed in fields param are OK.

onFailedSubmit

Optional. If supplied, it will be called with the param (usually event) passed to the handleSubmit handler only if at least one field listed in fields param is not OK. Defaults to function that prevents default event handling.

fields

Required. Array of objects produced by useFormField hooks.

Validation

Simple form

validate function may return an error message if validation fails and any falsy value if it succeeds.

Example:

validate: value => value.length < 5
  ? 'Value must be at least 5 characters long'
  : null

When above validation fails, the field shape will have keys:

{
  successfulValidations: [],
  validationErrors: ['Value must be at least 5 characters long'],
  isInvalid: true,
  isValid: false,
  ...other
}

When above validation succeeds, the field shape will have keys:

{
  successfulValidations: [],
  validationErrors: [],
  isInvalid: false,
  isValid: true,
  ...other
}

Note: since in this form validate only returns errorMessage on failure, successfulValidations will always be an empty array.

Multiple errors

There may be multiple problems with the value that is being validated and it may be a good idea to let user know of all of them instead of presenting only one at a time.

validate function may return an array of validation error messages.

A good example is a password field:

validate: password => {
  const errorMessages = [];
  if (password.length < 5) {
    errorMessages.push('Password must be at least 5 characters long');
  }
  if (!RegExp(/.*[A-Z]+.*/g).test(password)) {
    errorMessages.push('Password must include at least one uppercase letter');
  }
  if (!RegExp(/.*[a-z]+.*/g).test(password)) {
    errorMessages.push('Password must include at least one lowercase letter');
  }
  return errorMessages;
}

When above validation fails, the field shape will have keys:

// ex. value = 'test';
{
  successfulValidations: [],
  validationErrors: [
    'Password must be at least 5 characters long',
    'Password must include at least one uppercase letter'
  ],
  isInvalid: true,
  isValid: false,
  ...other
}

When above validation succeeds, the field shape will have keys:

{
  successfulValidations: [],
  validationErrors: [],
  isInvalid: false,
  isValid: true,
  ...other
}

Note: since in this form validate only returns errorMessages, successfulValidations will always be an empty array.

Successful Validations

If you would like to be explicit about what validations suceeded, validate function may return an array with two items in it: [validationErrors, successfulValidations]. First item is an array of validation error messages. The second item is an array of successful validation messages.

Example:

validate: password => {
  const errorMessages = [];
  const successfulValidations = [];
  if (password.length < 5) {
    errorMessages.push('Password must be at least 5 characters long');
  } else {
    successfulValidations.push('Password is long enough');
  }
  if (!RegExp(/.*[A-Z]+.*/g).test(password)) {
    errorMessages.push('Password must include at least one uppercase letter');
  } else {
    successfulValidations.push('Password has an uppercase letter');
  }
  if (!RegExp(/.*[a-z]+.*/g).test(password)) {
    errorMessages.push('Password must include at least one lowercase letter');
  } else {
    successfulValidations.push('Password has a lowercase letter');
  }
  return [errorMessages, successfulValidations];
}

When above validation fails, the field shape will have keys:

// ex. value = 'test';
{
  successfulValidations: [
    'Password has a lowercase letter'
  ],
  validationErrors: [
    'Password must be at least 5 characters long',
    'Password must include at least one uppercase letter'
  ],
  isInvalid: true,
  isValid: false,
  ...other
}

When above validation succeeds, the field shape will have keys:

{
  successfulValidations: [
    'Password is long enough',
    'Password has an uppercase letter',
    'Password has a lowercase letter'
  ],
  validationErrors: [],
  isInvalid: false,
  isValid: true,
  ...other
}

Async validation

In some cases validation requires an async operation. For example, making an API call to check if username is taken.

COMING SOON

Validating dependant fields

Sometimes, field validation depends on another field. A simple example is a password repeat field that needs to compare repeat field value to password field value.

This is where react hooks shine: if both fields are in scope of the same functional component, value of one field can be accessed in validate function of another.

Example:

function PasswordsMatch(props) {
  const password = useFormField(); // no validation for simplicity
  const passwordRepeat = useFormField({
    validate: value => value !== password
      ? 'Passwords must match'
      : null
  });
}

To validate both fields:

function PasswordsMatch(props) {
  const password = useFormField({
    validate: validateMatchesPasswordRepeat
  });
  const passwordRepeat = useFormField({
    validate: validateMatchesPassword
  });

  function validateMatchesPasswordRepeat(value) {
    return value !== passwordRepeat
      ? 'Passwords must match'
      : null;
  }

  function validateMatchesPassword(value) {
    return value !== password
      ? 'Passwords must match'
      : null;
  }
}

Development and contributions

yarn

git clone https://github.com/AntonRublev360/react-use-form-hooks.git
cd react-use-form-hooks
yarn install
yarn start

npm

git clone https://github.com/AntonRublev360/react-use-form-hooks.git
cd react-use-form-hooks
npm i
npm start

License

MIT