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

uniformed

v1.0.1

Published

Trying really hard to define a non-standard standard for React forms.

Downloads

1

Readme

Uniformed ⚛️

I got really fed up with the way you do forms in React. I also don't like the sheer autocracy that other solutions tend to impose over the way you do forms.

So, I created uniformed as an attempted solution to all of these problems.

Its fundamental principle is being very, very...

small

It currently clocks in at 1.08kB gzipped, which is probably less than a tenth of the competition.

I'd argue that forms are so different, that it's really a bad idea to assume anything other than the most essential function of changing values in objects.

I do have plans to make Uniformed highly extensible, so that it becomes really easy to include stuff like pristine checking and error validation as simple "middlewares" or sorts. Do check back sometime soon.

Getting Started

The most fundamental principle to uniformed is the storage and manipulation of a single, flat object. That's it. Nothing crazy at all.

Let's say I want to build a form that lets a user type in their name and their email address. In its most basic form (ba-dum-tss), this information can be represented as follows,

{
  email: <some string>,
  name: <some string>
}

And I really wanted to make sure that that type of raw simplicity was kept in uniformed. Everything you do in uniformed will revolve around the manipulation and retrieval of information in this simple, flat object. Nothing more.

Syntax

uniformed works as a HOC (Higher-Order Component) that sits on top of your form. Let's go with that example of a name / email form, that currently looks something like this:

import React from 'react';

const Form = () => {
  return (
    <form>
      <input placeholder="Name" type="text" />
      <input placeholder="Email" type="text" />
    </form>
  );
};

export default Form;

Step 1 would be doing this:

import React from "react";
import { uniform } from "uniformed";

const Form = ({ uniformed: { handlers, state } }) => {
  return (
    <form>
      <input onChange={handlers.name} placeholder="Name" type="text" value={state.name} />
      <input onChange={handlers.email} placeholder="Email" type="text" value={state.email} />
    </form>
  );
};

const configObj = {
  initialValues: {
    email: "",
    name: ""
  }
};

export default uniform(configObj)(Form);

This immediately binds the values for name and email into an internal "state" on the Higher-Order Component. It's that easy.

uniformed brings in a prop called uniformed, containing two properties:

  • handlers - this is an object containing a bunch of handlers, methods that do stuff to the state (more correctly, can do stuff to the state)
  • state - this is an object containing all of the state values you specified in initialValues.

Wait a second, where did the two handlers come from? We didn't define those!

That's correct. uniformed automatically defines a handler for each key that you specify in initialValues, unless you override it with your own.

Configuration

Right now the uniformed method takes a single parameter configObj, which takes two properties:

  • initialValues - an object of key-value pairs. See above for the full gist of how this currently works. I'm planning to update this to include functional resolution as well, so stay tuned (or submit a pull request, why not)
  • handlers - an object of key-value pairs. The value of each should be a method, which will be called every time the handler is called (generally on the onChange event). The handler will be called with a single argument handlerArgObj, containing: - props - a direct passthrough of the component's props. - state - a set of all the current values of the form.
  • Up to 1 dynamic property - if the handler's key also exists in initialValues, a $-prefixed property will be passed with the new value of that property passed in. For example, if a handler is defined under name where this is also found in initialValues, then when this handler is run, a $name property will also be passed in, with the new value that is to be assigned to the name field. Note that when the handler method is called, the value hasn't been changed in the form state yet - you will need to do this yourself using the update method (see next dot point)
  • update - this method can be called multiple times, and takes in a single object. When called, the keys in this object will be overlaid over the existing form state, updating one or more values in the form.

Let's refer to our previous example:

import React from "react";
import { uniform } from "uniformed";

const Form = ({ uniformed: { handlers, state } }) => {
  return (
    <form>
      <input onChange={handlers.name} placeholder="Name" type="text" value={state.name} />
      <input onChange={handlers.email} placeholder="Email" type="text" value={state.email} />
    </form>
  );
};

const configObj = {
  initialValues: {
    email: "",
    name: ""
  }
};

export default uniform(configObj)(Form);

Let's say we want to update the email address to <name>@gmail.com whenever the name is changed:

import React from "react";
import { uniform } from "uniformed";

const Form = ({ uniformed: { handlers, state } }) => {
  return (
    <form>
      <input onChange={handlers.name} placeholder="Name" type="text" value={state.name} />
      <input onChange={handlers.email} placeholder="Email" type="text" value={state.email} />
    </form>
  );
};

const configObj = {
  handlers: {
    name: ({ $name, props, state, update }) => {
      return update({
        email: $name + "@gmail.com",
        name: $name // you need to do this so that the name can actually change
      });
    }
  },
  initialValues: {
    email: "",
    name: ""
  }
};

export default uniform(configObj)(Form);

This type of simple, non-restrictive design allows us to do special promise magic here too!

handlers: {
  name: async ({ $name, props, state, update }) => {
    await firstPromise();
    update({
      anything: "you want"
    })
    await secondPromise();
    return update({
      anything: "you want"
    });
  }
}

I think that gives uniformed a special level of power over other React form libraries, simply because of how little it assumes.

License

© Lucas Chen, 2018. MIT licensed.