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

@dldc/formi-react

v3.0.0

Published

React form hook

Downloads

227

Readme

📄 Formi React

A type-safe form librairy for React

Features

  • 🍰 Easy to use: React Formi provides a simple API to create forms, and a simple way to use them in your components.
  • 🔒 Type safe: React Formi is built with TypeScript and provides type safety for your forms, including typing field validation issues !
  • FormData based: React Formi manipulates the native FormData API, this mean that you can validate your form on the backend with the same code as on the frontend.
  • 🪶 Very few dependencies: React Formi only has a few dependencies (2 at the time of writing).
  • 🔐 Server validation: With React Formi you can validate your form on the server using the same schema as on the frontend as well as a way to display the validation issues.
  • 🚀 Fast: React Formi is built with performance in mind so your components only render when they need to.
  • 🛡 Zod validation: React Formi offers convinient tools to validate your form with Zod but you can use any validation library you want (and zod is not a dependency of React Formi).
  • 🛠 Transformations: React Formi offers a way to transform your form data, this allow your form to output data in the shape you want.
  • 🧩 Dynamic fields: With React Formi you can dynamically change the shape of your form and it's not limited to arrays !

Motivations

This library is heavily inspired by react-zorm. It uses the same principle of using the FormData API at its core, to allow for easy validation on the backend. In other words, you can validate your form on the backend with the same code you use to validate the form on the frontend. Where this library differs from react-zorm is that it does not use zod to defined the shape of your form and has some additional features like dynamic fields.

Gist

import React from 'react';
import { FormiField, useFormi } from '@dldc/formi-react';
import { TextInput } from './TextInput';

/**
 * 1. Define the form fields
 */
const simpleFields = {
  username: FormiField.string(),
  email: FormiField.string(),
  password: FormiField.string(),
};

export function ComponentsExample() {
  /**
   * 2. Use the useFormi hook to create a form instance
   */
  const { fields, Form } = useFormi({
    formName: 'components',
    initialFields: simpleFields,
  });

  return (
    <Form>
      <h2>Components</h2>
      <p>
        In this example we use a custom <code>TextInput</code> component. We use <code>useFormiFieldState</code> to get
        the state of a field and display validation errors.
      </p>
      <TextInput label="Username" field={fields.username} type="text" defaultValue="my-username" />
      <TextInput label="Email" field={fields.email} type="email" />
      <TextInput label="Password" field={fields.password} type="password" />
      <div className="buttons">
        <button type="submit">Submit</button>
        <button type="reset">Reset</button>
      </div>
    </Form>
  );
}

type TextInputProps = {
  label: string;
  field: IFormiField<string, TFormiIssue>;
  type: 'password' | 'text' | 'email';
  defaultValue?: string;
};

function TextInput({ label, field, type, defaultValue }: TextInputProps) {
  const state = useFieldState(field);
  const id = useId();

  return (
    <div className="input">
      <label htmlFor={id}>{label}</label>
      <input id={id} type={type} name={state.name} defaultValue={defaultValue} />
      {state.touchedIssues && <IssueBox issues={state.touchedIssues} />}
    </div>
  );
}

Installation

npm install react-formi
# or
yarn add react-formi

How it works

React Formi let the browser handle the state of each inputs (they are uncontrolled). But that does not mean that React Formi has no state. React Formi is in charge of two things:

  • The state of the shape of the form (the structure, or schema of the form) and the names of the inputs.
  • The state of the validation and transformation of the form (field issues, submitted, etc).

To do so, React Formi only needs a ref to the form element, then it listens to the change, reset and submit events to update its state.

Note: The change event of the form element is only triggered when the user blurs an input (click outside / press tab) with a different value. This means that with React Formi you don't get validation as you type (you can if you really want). This behavior is the same as the default one in the browser and garantees that writing in an input is always fast.

Internally React Formi uses two data structures to keep track of the state of the form:

  • A tree of fields for the shape of the form, each field has a key that identifies it
  • A Map to keep the validation state of each field (identified by its key)

Examples

You can find many examples in the examples folder. You can run them with:

yarn example:run

API

TODO