fractal-form v0.1.0
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-formUsage
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.
formis the entire form state, an object composed of keys{ value, error, touched }.valuecontains the form values. Initially set toinitialValues.errorcontains the errors. Initially set to{}touchedcontains 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*Lensare hooks which provide lenses to each one of the properties. They are the same asuseLenshooks returned fromuseLensState(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.
nameFieldis a utility object containing thevalue,error, andtouchedvalues for the given field name as well asonChange(updates the value and validates it) andonBlur(setstouchedto true) callbacks.setNameFieldexpects an object of{ value, error, touched }for the given fielduseNameFieldLensis a lens for the value, error and touched for the given field. It can be provided as the first argument to anotheruseLensField
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 => atakes a full statesand returns a partial stateaupdate: (s, a) => ttakes a full statesand a new partial stateaand returns a new full statet
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.
3 years ago