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

@jhadev/use-form

v0.0.4

Published

React hook to quickly generate simple forms.

Readme

React hook to generate simple forms.

in progress

EXPERIMENTAL

There may be bugs and this only suits certain use cases.

npm install or yarn add @jhadev/use-form

uses bootstrap by default but can be customized.

0.0.4 - support for textarea (define textarea in the option object)

Next version will support an entire form rather than only inputs.

{
  textarea: { rows: 4, maxLength: 200 },
  placeholder: 'this is a text area'
}

usage

Examples:


In any functional component...

import React from 'react';
import { useForm } from '@jhadev/use-form';

const SomeForm = props => {

  // initial state is first argument to useForm, name of form is second argument.

  const { formState, setFormState, onChange, mapInputs } = useForm({

    // initialize state here

  }, 'some-form');

  ...
}

export default SomeForm

Input changes are handled automatically.

Defaults to bootstrap form-control class names for inputs if no options are specified. If no ids are specified it will create ids based on the form name and the key in state.

If useForm is used in multiple components, the form name must be unique to that component. This ensures ids will not be duplicated, but will still be styleable because they won't be randomly generated.

If no name is specified as the second argument the name of the form will be set as 'default'. This means if another form is not named, there will be duplicate ids. It is just a fallback.

  • ex: If a key in state is named age and the form is named form-one then id="form-one-age"

  • setFormState behaves just like this.setState

  ...

  const { formState, setFormState, onChange, mapInputs } = useForm({
    email: '',
    password: '',
    success: false,
    error: null
  }, 'sign-in-form');

  ...

  const signInUser = () => {
    const { email, password } = formState

    props.firebase.signInWithEmailAndPassword(email, password)
      .then(response => {
        setFormState({ email: '', password: '', success: true })
        ....
      }).catch(error => {
        setFormState({ error, success: false })
      })
  }

  ...

Map all of state to inputs with no options

  • onChange is optional because it is already handled, but it is still available if needed.

Example all of state no options

  const { formState, setFormState, onChange, mapInputs } = useForm({
    name: '',
    password: ''
  }, 'example-state-form');

  const displayInputs = mapInputs(formState)()

  ...
  return (
    ...
    <div className='form-group'>{displayInputs}</div>
    ...
  )

HTML Output

<div class="form-group">
  <input
    class="form-control mb-3"
    id="example-state-form-name"
    type="text"
    placeholder="Name"
    name="name"
    value=""/>
  <input
    class="form-control mb-3"
    id="example-state-form-password"
    type="password"
    placeholder="Password"
    name="password"
    value=""/>
</div>

Map some of state into inputs

Filter state example

  const { formState, setFormState, onChange, mapInputs } = useForm({
    name: '',
    password: '',
    success: false,
    error: null
  }, 'example-filter-form');

  // second optional argument of mapInputs is an array of certain state values as strings to create into inputs

  const displayInputs = mapInputs(formState, ['name', 'password'])();

  ...
  return (
    ...
    <div className='form-group'>{displayInputs}</div>
    ...
  )

HTML Output

<div class="form-group">
  <input
    class="form-control mb-3"
    id="example-only-filter-name"
    type="text"
    placeholder="Name"
    name="name"
    value=""/>
  <input
    class="form-control mb-3"
    id="example-only-filter-password"
    type="password"
    placeholder="Password"
    name="password"
    value=""/>
</div>

Map all of state into inputs with options

Options are: label, id, className, placeholder, type, textarea

There is no need to define classNames for every options object if they are all the same. If a className property exists for the first options object, it will be automatically added to the rest of the inputs. If classNames exist for any of the following option objects, they will not be replaced.

Labels are off by default. If a label is specified for an input field, but no id is provided, an id will be created to match the label's htmlFor property.

To define a textarea create a property in the object called 'textarea', and define either an empty object inside it for no options, or define rows and/or maxLength. Default row size is 3.

{
  textarea: { rows: 4, maxLength: 200 },
  placeholder: 'this is a text area'
}

OR

{
  textarea: {},
  placeholder: 'this is a text area'
}
const types = [
  'date',
  'datetime-local',
  'email',
  'number',
  'password',
  'range',
  'search',
  'tel',
  'time',
  'url',
  'week',
  'month'
]

/*
  If the key in state matches one of these types it will be used as the type for the input field.
  If it does not match and no type is specified for that input field,
  the type will default to 'text'.
*/

Example with options

  const { formState, setFormState, onChange, mapInputs } = useForm({
    name: '',
    password: '',
    age: '',
  }, 'example-options-form');

  // If an input does not need options, insert an empty object as the placeholder. The order matters.

  const formOptions = [
    {
      label: 'Enter your name.',
      placeholder: 'Your Name Here',
      type: 'text',
      id: 'name-field'
    },
    {},
    { label: 'How old are you?', type: 'number' }
  ];

  const displayInputs = mapInputs(formState)(formOptions);

  return (
    ...
    <div className='form-group'>{displayInputs}</div>
    ...
  )

HTML output

<div class="form-group">
  <label for="name-field">Enter your name.</label>
  <input
    class="form-control mb-3"
    id="name-field"
    type="text"
    placeholder="Your Name Here"
    name="name"
    value=""/>
  <input
    class="form-control mb-3"
    id="example-options-form-password"
    type="password"
    placeholder="Password"
    name="password"
    value=""/>
  <label for="example-options-form-age">How old are you?</label>
  <input
    class="form-control mb-3"
    id="example-options-form-age"
    type="number"
    placeholder="Age"
    name="age"
    value=""/>
</div>

Map and filter state into inputs with options

Filter and options example

const { formState, setFormState, onChange, mapInputs } = useForm({
    name: '',
    password: '',
    success: false
  }, 'example-all-form');

  /*
    Order matters.
    Options are label, id, className, placeholder, type.
    If className property exists for the first item,
    it will be automatically added to the rest of the inputs.
    If classNames exist for any of the following objects,
    they will not be replaced.
  */

  const formOptions = [
    {
      label: 'Enter your name.',
      placeholder: 'Do you even have a name?',
      type: 'text',
      className: 'form-control my-2'
    },
    { id: 'password-field' }
  ];

  // mapInputs second argument is an array to filter the inputs that need to be created.

  const displayInputs = mapInputs(formState, ['name', 'password'])(formOptions);

  ...
  return (
    ...
    <div className='form-group'>{displayInputs}</div>
    ...
  )

HTML Output

<div class="form-group">
  <label for="example-all-form-name">Enter your name.</label>
  <input
    class="form-control my-2"
    id="example-all-form-name"
    type="text"
    placeholder="Do you even have a name?"
    name="name"
    value=""/>
  <input
    class="form-control my-2"
    id="password-field"
    type="password"
    placeholder="Password"
    name="password"
    value=""/>
</div>

❤ if you read this far.