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

@rageix/former

v0.2.3

Published

A headless form hook for React.

Readme

former

What is it

A headless React form component. It allows you to specify form fields, which will then create child form controllers with separate states. All form controls will update in their own independent states, allow the field to update just itself instead of all fields.

Being headless means that it does not create any form components itself and works with any forms you already have.

How to install

npm install --save @rageix/former

Examples

See the /examples directory.

Getting started

Create a new instance of the Former class and define the initial form.

import Former from '@rageix/former';

// define our form
interface SignUpForm {
  email: string;
  password: string;
  passwordAgain: string;
  count: number,
  terms: boolean;
}

// create a new instances of the Former class
const form = new Former<SignUpForm>({
  defaultValues: {
    email: '',
    password: '',
    passwordAgain: '',
    count: 10,
    terms: true,
  },
});

Keep in mind that form fields can be strings, numbers, and booleans. When the form field changes it will automatically be cast into the same type.

Hooks

In your form call the useForm() method which will call the proper useState functions for all the child components. This useForm() method takes a callback function that fires when the form submits.

function App() {
  form.useForm((value: SignUpForm) => {
    // do submit logic here
    console.log(value);
  });

Now you want to setup your form and attach the proper handlers to the form element.

<form {...form.getFormProps()}>
  {/* children here */}
</form>

The getformProps() method will set the onSubmit handler to the internal Former functions. This is optional if you do not want to use the onSubmit handler.

Form fields

Next up add your form fields here is a simple example:

<form.Field
  name="email"
  validate={(value) => {
    const result = z.string().email().safeParse(value);
    if (!result.success) {
      return result.error.issues.map((v) => v.message);
    }
  }}
  // this is just an example
  transformValue={(value) => value}
  children={(field) => (
    <div>
      <label htmlFor="email">Email</label>
      <input
        name="email"
        data-testid="email"
        {...field.getValueProps()}
      />
      <FormErrors errors={field.state.errors} />
    </div>
  )}
/>

Let's talk about this from top to bottom.

The name prop is the name of the field you used in defaultValues when creating a new instance of Former.

The validate props is a function used to validate the field. It returns a string[] of errors.

The transformValue prop is used to transform the input value. The user enters a value, the onChange handler is called, Former converts it into the type that was set in defaultValues, then the transformValue function is called if it is set. This method takes an argument of the value, and you can return whatever value you want and that is the value that gets set.

The children props is the standard React child prop. However, a controller for the field is passed as the first argument. This controller contains everything about the field.

The field.getValueProps() method returns the value and onChange handlers for the component. This is the method to use when your component needs a value prop passed. There is a field.getCheckedProps() for when the filed needs a checked prop.

To access the field errors you can do so though field.state.errors which is a string[].

Form button

Lastly is some kind of submit button for the form, and you have 2 options.

  1. If you used the getFormProps() method on your form element you just need a basic submit button.
<button
  type="submit"
  disabled={!form.valid}
>
  Submit
</button>
  1. If you want the form button to trigger the submit, or handle it in another way you can add the form.getSubmitButtonProps() method to any component and it will add the proper click handler to whatever component it's on. You could also directly call the form.submit() method if you wanted to manually trigger a submit.

Getters

form.getValue(name) - Allows you to get the value of any field by it's name.

form.getValues() - Allows you to get all the values in the form.

Setters

form.setValues(values) - Allows you to pass in a Partial of your form data to set any fields.