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 🙏

© 2026 – Pkg Stats / Ryan Hefner

react-use-validator

v1.0.4

Published

A React Hook to handle form validation messages

Downloads

11

Readme

React Validator Hook

A React Hook to handle form validation messages.

Features:

  • multiple rules per field
  • asynchronous rules with built-in concurrency prevention
  • BYO rules and display logic

Install

npm i react-use-validator

Usage

See validator-creator for background information about validator rules.

import React, { useState } from "react";
import useValidator, { createRule } from "react-use-validator";

const initialFormData = {
  field1: "",
  field2: ""
};

// A rule defines how a value should be validated. This is a rule that ensures
// string values aren't empty.
const filled = createRule("filled", value => value.length > 0, "Required");

function ExampleForm() {
  const [formData, setFormData] = useState(initialFormData);

  // useValidator() accepts a "rule collection" listing the validation rules
  // to apply to each field.
  // The `messages` element contains the messages for fields that have failed.
  // The `validate` element is a function used to perform a validation.
  const [messages, validate] = useValidator({
    field1: [filled],
    field2: [filled]
  });

  function handleChange({ target: { name, value } }) {
    const change = { [name]: value };
    setFormData({ ...formData, ...change });
    // the change is validated which will update `messages` if there's a change
    // to the validation results
    validate(change);
  }

  async function handleSubmit() {
    // the whole form is validated prior to submitting
    const messages = await validate(formData);
    if (
      Object.entries(messages).filter(([prop, result]) => result !== null)
        .length > 0
    ) {
      // abort as there's at least one non-null message
      return;
    }
    // continue as there are no validation messages
    await API.submit(formData); // or something
  }

  return (
    <div>
      <div>
        <label>Field 1</label>
        <input name="field1" value={formData.field1} onChange={handleChange} />
        // The message output will display "Required" from the `filled` rule if
        // the input value is empty
        <span>{messages.field1}</span>
      </div>
      <div>
        <label>Field 2</label>
        <input name="field2" value={formData.field2} onChange={handleChange} />
        <span>{messages.field2}</span>
      </div>
      <button onClick={handleSubmit}>Submit</button>
    </div>
  );
}

Asynchronous rules

The validator handles asynchronous validation rules (such as server-side validation), but some care is required.

An asynchronous rule can be created using the createAsyncRule function.

import { createAsyncRule } from "react-use-validator";
import API from "./api";

// createAsyncRule(validate, payload) is used to create a rule function
// The `validate` argument is a callback provided by your app. It should return
// a promise that resolves with a list of validation results. A validation result
// is an object with shape `{ type, prop }` which identifies the rule (`type`) and
// field (`prop`) that triggered the error
// The `payload` argument allows control over the error message.
const server = createAsyncRule(
  change => API.validate(change),
  ({ type, prop }) => `Error from server`
);

The rule can be added to a rule collection in the same way as for synchronous rules.

const rules = {
  field1: [filled, server],
  field2: [filled, server]
};
  • Rules are executed in the order they appear in the rule collection, stopping at the first one that returns a non-null response.
  • Asynchronous rules will only be called once per validation.

The validate() function returned by useValidator will prevent concurrent calls to the same rule by throwing a ValidatorError exception if a call is interrupted. This exception should be caught (and usually ignored) by the Component

function ignoreValidatorError(error) {
  if (!(error instanceof ValidatorError)) {
    throw error;
  }
}

async function handleChange({ target: { name, value } }) {
  const change = { [name]: value };
  setFormData({ ...formData, ...change });
  await validate(change).catch(ignoreValidatorError);
}

If a "submit" event occurs while an asynchronous validation is still in progress the event handler can block until the validation completes by calling validate() with no arguments. Again, ValidatorError exceptions should be caught and used to prevent further execution of the handler.

async function handleSubmit() {
  try {
    const messages = await validate();
    // ... check if there are any messages ...
  } catch (error) {
    return ignoreValidatorError(error);
  }
  // ... continue submitting data ...
}

Even after all validation rules have passed, submitting form data to the server may still fail. If the server response contains a list of errors with validation results ({ type, prop } objects) the validator can be re-run providing those errors so that another network request isn't needed.

async function handleSubmit() {
  // ... check there are no messages ...
  const response = await API.submit(formData);
  if (response.errors) {
    // inject server errors into the validator
    await validate(formData, [[server, response.errors]]);
  } else {
    // ... handle successful submit ...
  }
}