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

fractal-form

v0.1.0

Published

An experimental React form library using lenses.

Downloads

0

Readme

fractal-form

An experimental React form library using lenses. Lenses are a concept from functional programming. They are modular data accessors that play nice with immutable data. A big advantage of lens implementation in this library is that they are self-similar, so you can create reusable form components at any level of nesting in your application state.

This library is heavily inspired by André Staltz's use-profunctor-state.

See src/Example.js for an example implementation.

Installation

npm install fractal-form

Usage

Basic example

import { memo, useState } from "react"
import { useFractalForm, useLensField } from "fractal-form"

const Input = memo(({ label, value, onChange }) => (
  <label>{label}:
    <input value={value} onChange={onChange} />
  </label>
))

export const Basic = () => {
  const [submittedValues, setSubmittedValues] = useState({})
  const {useFormLens, value} = useFractalForm({ name: '' })
  const [nameField] = useLensField(useFormLens, 'name')

  const submitForm = () => setSubmittedValues(value)
  
  return (
    <div>
      <Input label="Name" {...nameField} />
      <button onClick={submitForm}>Submit form</button>
      <pre>{JSON.stringify(submittedValues, null, 2)}</pre>
    </div>
  )
}

API Reference

useFractalForm

const initialValues = { name: 'Bob' }
const {
  form, value, error, touched,
  setForm, setValues, setErrors, setTouched,
  useFormLens, useValuesLens, useErrorsLens, useTouchedLens,
} = useFractalForm(initialValues)

Create a form object for a given initial state.

  • form is the entire form state, an object composed of keys { value, error, touched }.

  • value contains the form values. Initially set to initialValues.

  • error contains the errors. Initially set to {}

  • touched contains the touched status of the fields. Initally set to {}

  • set* are functions that set the given object outright. You probably should avoid using those.

  • use*Lens are hooks which provide lenses to each one of the properties. They are the same as useLens hooks returned from useLensState (see below).

useLensField

const validateName = (_parentValue, name) => name.length < 5 ? "Name too short" : null

const { useFormLens } = useFractalForm({ name: 'Bob' })

const [nameField, setNameField, useNameFieldLens] = useLensField(useFormLens, 'name', validateName)

return (
  <input {...nameField} />
)

This hook creates a lens that focuses on a particular field name from the value, touched, and error object.

  • nameField is a utility object containing the value, error, and touched values for the given field name as well as onChange (updates the value and validates it) and onBlur (sets touched to true) callbacks.
  • setNameField expects an object of { value, error, touched } for the given field
  • useNameFieldLens is a lens for the value, error and touched for the given field. It can be provided as the first argument to another useLensField

useLensState

  const [state, setState, useLens] = useLensState({ name: 'Bob' })
  const [name, setName] = useLens(s => s.name, (s, a) => ({ ...s, name: a }))

  console.log(state) // -> { name: 'Bob' }
  console.log(name) // -> 'Bob'

  setName('Alice')

  console.log(name) // -> 'Alice'
  console.log(state) // -> { name: 'Alice' }

  setState({ name: 'Charles' })

  console.log(name) // -> 'Charles'

This hook is exactly the same as React's useState except it adds another element to the array. useLens is a hook that takes two functions:

  • view: s => a takes a full state s and returns a partial state a
  • update: (s, a) => t takes a full state s and a new partial state a and returns a new full state t

The two states are going to be synchronised.

The lenses are memoized so most of the time wrapping a component which uses them in React.memo should prevent unnecessary rerenders.

lensForProp

const [state, setState, useLens] = useLensState({ name: 'Bob' })
const [name, setName] = useLens(...lensForProp('name'))

A helper which takes a key name returns a pair of functions [view, update] for that key name.