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 🙏

© 2024 – Pkg Stats / Ryan Hefner

@zzzzbov/usefield

v0.1.1

Published

`useField` is a react hook for managing synchronous field validation alongside state.

Downloads

2

Readme

useField react hook

useField is a react hook for managing synchronous field validation alongside state.

useField is meant for simple forms with a few fields and limited field validation needs.

Contents

When not to useField

  • if your form has more than ~7 fields
  • if your fields don't need validation
  • if you need asynchronous field validation
  • if you want to manage validation on complex data structures, such as deeply nested objects, or dynamic collections of field data.

Installation

npm install @zzzzbov/usefield

Usage

import React, { useCallback } from 'react'

// Import the useField hook along with any needed validators
import { useField, required } from '@zzzzbov/usefield'

// `useField` can be used within any react control.
// This one is an example login form.
export const LogInForm = ({
  // The onSubmit property here is used as an example to externalize the
  // submitted form data. This is done to keep the example brief but is not
  // strictly necessary.
  onSubmit
}) => {
  // Call the `useField` hook passing in as few or as many validators as
  // desired, along with an initial field value. In this case a single required
  // field validator is used.
  const username = useField({
    required
  }, '')

  // `useField` can be called as many times as needed for as many fields as
  // needed. While this makes managing data very straightforward, it may be too
  // verbose for complex forms that have more than a handful of fields.
  const password = useField({
    required
  }, '')

  // Set up a callback for the form submission
  const internalSubmit = useCallback((e) => {
    e.preventDefault()

    // Mark the fields as dirty since the fields might not have been edited yet
    username.touch()
    password.touch()

    // Check that the fields are valid.
    // Use the `valid` properties and NOT the `error` helpers as the error
    // helpers will return false if the fields are clean.
    if (username.valid && password.valid) {
      // Handle the form submission behavior.
      // This example uses an onSubmit property to keep things simple.
      onSubmit(username.value, password.value)
    }
  }, [onSubmit, username, password])

  return (
    <form
      method='POST'

      // Bind the submit callback on the form to take advantage of native form
      // submission behaviors, such as implicit form submission.
      onSubmit={internalSubmit}>
      <h1>Log In</h1>
      <div className='Field'>
        <label htmlFor='username'>Username:</label>
        {/*
          Display an error message to the user.
          
          If multiple validators are used, it may be desirable to check each
          validator explicitly, such as:

          { username.dirty && !username.validation.required && (
            <p>Username is required</p>
          ) }

          Alternatively, validator-specific messages may be left visible so
          that their current state is visibly toggled as the user changes the
          field value:

          <p>
            { username.validation.required ? '☑ ' : '☐ ' }
            Username is required
          </p>
         */}
        { username.error && (
          <p id='username-error'>Username is required</p>
        ) }
        <input
          // The `error` property can be used to visually indicate an issue to 
          // the user such as by toggling a class.
          className={username.error ? 'error' : ''}
          id='username'
          name='u'
          type='text'
          aria-describedby='username-error'

          // Pass the current value to the field
          value={username.value}

          // Bind the `set()` method to the field.
          // Some extra boilerplate is used to access the current field value.
          // If the field should be marked as dirty, call touch as well:
          //
          // onChange={e => {
          //   username.set(e.target.value)
          //   username.touch()
          // }}
          onChange={e => username.set(e.target.value)}

          // `touch()` is bound to the blur handler so that the field is flagged
          // as dirty only after the user has finished editing the field.
          onBlur={username.touch}
        />
      </div>
      <div className='Field'>
        <label htmlFor='password'>Password:</label>
        { password.error && (
          <p id='password-error'>Password is required</p>
        ) }
        <input
          className={password.error ? 'error' : ''}
          id='password'
          name='p'
          type='password'
          aria-describedby='password-error'
          value={password.value}
          onChange={e => password.set(e.target.value)}
          onBlur={password.touch}
        />
      </div>
      {/*
        A single submit button is used here to submit the form.
        If a reset button is also desirable, it may be added, and an `onReset`
        handler should be added to the <form> to reset the fields:

        onReset={() => {
          username.reset()
          password.reset()
        }}
      */}
      <button type='submit'>
        Log In
      </button>
    </form>
  )
}

Visit https://zzzzbov.github.io/useField-demo/ for a live demo.

API

useField(validators, initialValue)

The useField hook accepts a map of validators and an initial value and returns an object with the current value, utility methods, and validation state.

validators

The validators parameter is an object of functions to validate the field.

Each validator takes a single parameter of the current value, and should return true when the provided value is valid, and false when the provided value is invalid.

initialValue

The initialValue parameter specifies the initial value for the field before any user interaction occurs. While the primary use-case for useField is for string values, any type may be used.

Return value

useField returns an object with the following members:

clean()

The clean method marks the field as having been cleaned, which sets the dirty property to false, but does not otherwise change the current value.

See also: dirty, reset(), and touch()

dirty

Type: boolean
Default: false

The dirty property indicates whether the user has interacted with the field for purposes of displaying validation.

See also: clean(), error, reset(), and touch()

error

Type: boolean

Warning:

Do not use the error property for checking field validation in a form submit handler, as the fields may not have been considered dirty when the submission event occurs.

The error helper property indicates whether the field is dirty and not valid. This helper is meant to be used to indicate to a user that the field has an issue that should be fixed.

See also: dirty, and valid

reset()

The reset method sets the value property back to the originally provided initialValue and cleans the field (i.e. sets dirty to false).

See also: clean(), dirty, set(value), touch(), and value

set(value)

The set method sets the value property. It does not mark the field as dirty so that displaying validation may be delayed until a user is done with the given field.

See also: reset(), and value

touch()

The touch method marks the field as dirty, and does not change the field value.

See also: clean(), dirty, and reset()

valid

Type: boolean

The valid property indicates whether all of the provided validators are currently valid.

See also: validators

validation

Type: object

The validation property is an object of the results from each of the provided validators.

const example = useField({
  numeric (value) {
    return !isNaN(value)
  }
}, '')

example.validation.numeric
// after example.set('123') becomes true
// after example.set('abc') becomes false

See also: validation

value

The value property is the currently assigned field value.

See also: initialValue, reset(), and set(value)

Built-in validators

useField comes with a few built-in validator utilities which can be passed to the validators parameter of useField.

matches(regex)

matches creates a validator function to match the current value against a provided regular expression.

Usage:

import { useField, matches } from '@zzzzbov/usefield'

...

const example = useField({
  lowercase: matches(/a-z/),
  uppercase: matches(/A-Z/)
}, '')

example.validation.lowercase // false until the example field has a value that contains a lower case character

example.validation.uppercase // false until the example field has a value that contains an upper case character

maxLength(length)

maxLength creates a validator function to verify that the current value is no longer than the provided length.

Usage:

import { useField, maxLength } from '@zzzzbov/usefield'

...

const example = useField({
  max: maxLength(20)
}, '')

example.validation.max // true until the example field has a value longer than 20 characters

minLength(length)

minLength creates a validator function to verify that the current value is at least as long as the provided length.

Usage:

import { useField, minLength } from '@zzzzbov/usefield'

...

const example = useField({
  min: minLength(5)
}, '')

example.validation.min // false until the example field has a value that's at least 5 characters long

required

required is a validator function to verify that the current value is truthy (not 0, false, '', NaN, null, or undefined).

Usage:

import { useField, required } from '@zzzzbov/usefield'

...

const example = useField({
  required
}, '')

example.validation.required // false until the example field has a value