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

use-yup-hook-validate

v2.3.4

Published

A hook for fast form field validation without headache

Readme

🎯 use-yup-hook-validate

npm version CI Publish License: MIT

🚀 Zero-hassle React form validation with Yup

The simplest way to validate forms in React. No wrappers, no render props, no complexity.

Just Yup and You!

InstallationQuick StartExamplesAPIContributing


🌟 Why use-yup-hook-validate?

  • 🎯 Simple: Just one hook, one schema, done!
  • ⚡ Fast: Debounced validation with performance optimization
  • 🔧 Flexible: Works with any form structure
  • 📦 Lightweight: Minimal bundle size impact
  • 🛡️ Type-safe: Full TypeScript support
  • 🎨 Framework-agnostic: No UI library dependencies

� Installation

# npm
npm install use-yup-hook-validate

# yarn
yarn add use-yup-hook-validate

# pnpm
pnpm add use-yup-hook-validate

⚡ Quick Start

Transform your form validation from this mess:

// ❌ The old way - complex and verbose
const [errors, setErrors] = useState({});
const [touched, setTouched] = useState({});

const validateField = (name, value) => {
  // 50 lines of validation logic...
};

const handleBlur = (e) => {
  setTouched({ ...touched, [e.target.name]: true });
  validateField(e.target.name, e.target.value);
};

To this elegance:

// ✅ The use-yup-hook-validate way - clean and simple
import { useYupHookValidate, yup } from 'use-yup-hook-validate';

const schema = yup.object().shape({
  email: yup.string().email().required(),
  name: yup.string().required(),
});

const [validateField, isValid] = useYupHookValidate({
  validationSchema: schema,
  formState,
  updateErrorsCallback: setFormErrors,
});

📚 Examples

🎨 Basic Example

import React, { useState } from 'react';
import { useYupHookValidate, yup } from 'use-yup-hook-validate';

const ContactForm = () => {
  // 1️⃣ Define your form state
  const [formState, setFormState] = useState({
    name: '',
    email: '',
    phone: '',
    message: '',
  });

  // 2️⃣ Create your validation schema with custom methods
  const schema = yup.object().shape({
    name: yup.string().fullname('Please enter your full name').required(),
    email: yup.string().email('Invalid email format').required(),
    phone: yup.string().phone('Invalid phone number').required(),
    message: yup.string().min(10, 'Message too short').required(),
  });

  // 3️⃣ Set up form errors state
  const [formErrors, setFormErrors] = useState({});

  // 4️⃣ Initialize the validation hook
  const [validateField, isFormValid, resetValidation] = useYupHookValidate({
    validationSchema: schema,
    formState,
    updateErrorsCallback: setFormErrors,
    validationTimeout: 300, // Debounce for better UX
  });

  // 5️⃣ Create a reusable input handler
  const handleInputChange =
    (field: string) => (e: React.ChangeEvent<HTMLInputElement>) => {
      setFormState((prev) => ({ ...prev, [field]: e.target.value }));
    };

  const handleSubmit = (e: React.FormEvent) => {
    e.preventDefault();
    if (isFormValid) {
      console.log('Form is valid!', formState);
      // Submit your form
    }
  };

  return (
    <form onSubmit={handleSubmit} className="space-y-4">
      <div>
        <label className="block text-sm font-medium">Full Name</label>
        <input
          type="text"
          value={formState.name}
          onChange={handleInputChange('name')}
          onBlur={validateField('name')} // 🎯 Validate on blur
          className={`input ${formErrors.name ? 'border-red-500' : ''}`}
        />
        {formErrors.name && (
          <p className="text-red-500 text-sm mt-1">{formErrors.name}</p>
        )}
      </div>

      <div>
        <label className="block text-sm font-medium">Email</label>
        <input
          type="email"
          value={formState.email}
          onChange={handleInputChange('email')}
          onKeyUp={validateField('email')} // 🎯 Validate on keyup
          className={`input ${formErrors.email ? 'border-red-500' : ''}`}
        />
        {formErrors.email && (
          <p className="text-red-500 text-sm mt-1">{formErrors.email}</p>
        )}
      </div>

      <button
        type="submit"
        disabled={!isFormValid}
        className="btn-primary disabled:opacity-50"
      >
        {isFormValid ? '✅ Submit' : '❌ Complete Form'}
      </button>
    </form>
  );
};

🚀 Advanced Usage with Custom Validation

// Custom validation methods available out of the box
const advancedSchema = yup.object().shape({
  username: yup.string().min(3).max(20).required(),
  password: yup
    .string()
    .min(8)
    .matches(
      /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)/,
      'Password must contain uppercase, lowercase and number'
    )
    .required(),
  confirmPassword: yup
    .string()
    .oneOf([yup.ref('password')], 'Passwords must match')
    .required(),
  website: yup.string().url('Must be a valid URL'),
  age: yup.number().min(18, 'Must be 18+').max(120).required(),
  terms: yup.boolean().oneOf([true], 'You must accept terms'),
});

🎛️ Real-time Validation

// Validate as user types with debouncing
const [validateField] = useYupHookValidate({
  validationSchema: schema,
  formState,
  updateErrorsCallback: setFormErrors,
  validationTimeout: 500, // Wait 500ms after user stops typing
});

// Use with onChange for real-time feedback
<input
  onChange={(e) => {
    handleInputChange('email')(e);
    validateField('email')(e); // Real-time validation
  }}
/>;

� API Reference

useYupHookValidate(options)

Parameters

| Parameter | Type | Required | Default | Description | | ---------------------- | ----------- | -------- | ------- | -------------------------------- | | validationSchema | YupSchema | ✅ Yes | - | Your Yup validation schema | | formState | object | ✅ Yes | - | Your form state object | | updateErrorsCallback | function | ✅ Yes | - | Callback to update form errors | | validationTimeout | number | ❌ No | 300 | Debounce timeout in milliseconds |

Returns

Returns an array with three elements:

const [validateField, isFormValid, resetValidation] = useYupHookValidate(options);

| Return Value | Type | Description | | ----------------- | ----------------------------------------------- | --------------------------------------------- | | validateField | (fieldName: string) => (event: Event) => void | Function to validate specific field | | isFormValid | boolean | True when all required fields pass validation | | resetValidation | () => void | Function to reset all validation states |

🎯 Custom Yup Methods

This package extends Yup with additional validation methods:

// Available custom methods
yup.string().phone(); // Validates phone numbers
yup.string().fullname(); // Validates full name (first + last)
// More methods available - check the source!

🎨 Integration Examples

With Material-UI

import { TextField } from '@mui/material';

<TextField
  label="Email"
  value={formState.email}
  onChange={handleInputChange('email')}
  onBlur={validateField('email')}
  error={!!formErrors.email}
  helperText={formErrors.email}
  fullWidth
/>;

With Chakra UI

import { Input, FormControl, FormLabel, FormErrorMessage } from '@chakra-ui/react';

<FormControl isInvalid={!!formErrors.email}>
  <FormLabel>Email</FormLabel>
  <Input
    value={formState.email}
    onChange={handleInputChange('email')}
    onBlur={validateField('email')}
  />
  <FormErrorMessage>{formErrors.email}</FormErrorMessage>
</FormControl>;

With React Hook Form (Migration Helper)

// Easy migration from react-hook-form
const { register, formState: { errors } } = useForm();

// Replace with:
const [validateField] = useYupHookValidate({...});
const [formErrors, setFormErrors] = useState({});

🚀 Performance Tips

  1. Use validationTimeout for better UX during typing
  2. Memoize your schema to prevent unnecessary re-renders
  3. Use onBlur for less aggressive validation
  4. Batch state updates when possible
// ✅ Good - memoized schema
const schema = useMemo(
  () =>
    yup.object().shape({
      email: yup.string().email().required(),
    }),
  []
);

// ❌ Avoid - recreating schema on every render
const schema = yup.object().shape({
  email: yup.string().email().required(),
});

🆚 Comparison

| Feature | use-yup-hook-validate | Formik | React Hook Form | | ----------------- | --------------------- | --------------- | --------------- | | Bundle Size | 🟢 Small | 🟡 Medium | 🟢 Small | | Learning Curve | 🟢 Easy | 🟡 Medium | 🔴 Hard | | TypeScript | 🟢 Full Support | 🟢 Full Support | 🟢 Full Support | | Render Props | 🟢 None | 🔴 Required | 🟢 None | | Custom Validation | 🟢 Yup Schema | 🟢 Yup Schema | 🟡 Custom Logic | | Performance | 🟢 Optimized | 🟡 Good | 🟢 Optimized |

🎯 Migration Guide

From Formik

// Before (Formik)
<Formik initialValues={initialValues} validationSchema={schema} onSubmit={handleSubmit}>
  {({ values, errors, handleChange, handleBlur }) => (
    <Form>
      <Field name="email" onChange={handleChange} onBlur={handleBlur} />
      <ErrorMessage name="email" />
    </Form>
  )}
</Formik>;

// After (use-yup-hook-validate)
const [formState, setFormState] = useState(initialValues);
const [formErrors, setFormErrors] = useState({});
const [validateField, isValid] = useYupHookValidate({
  validationSchema: schema,
  formState,
  updateErrorsCallback: setFormErrors,
});

<form onSubmit={handleSubmit}>
  <input
    value={formState.email}
    onChange={handleInputChange('email')}
    onBlur={validateField('email')}
  />
  {formErrors.email && <span>{formErrors.email}</span>}
</form>;

🤝 Contributing

We love contributions! Here's how you can help:

  1. 🍴 Fork the repository
  2. 🌟 Create your feature branch (git checkout -b feature/amazing-feature)
  3. ✅ Add tests for your changes
  4. 💚 Make sure all tests pass (npm test)
  5. 📝 Commit your changes (git commit -m 'Add amazing feature')
  6. 🚀 Push to the branch (git push origin feature/amazing-feature)
  7. 🎉 Open a Pull Request

Development Setup

git clone https://github.com/dougvil/use-yup-hook-validate.git
cd use-yup-hook-validate
npm install
npm run build
npm run watch  # For development

📄 Changelog

See CHANGELOG.md for detailed release notes.

🙏 Acknowledgments

  • Built with ❤️ by Douglas Viliano
  • Powered by Yup validation library
  • Inspired by the React community's need for simpler form validation

⭐ Star this repo if it helped you! ⭐

Report BugRequest FeatureContribute

Made with 💻 and ☕ by developers, for developers.

Just Yup and You!