npm package: @stackup/form
Description: A type-safe approach to managing complex form state in React.
Author: rzane
Latest version: 0.3.7

<h1 align="center">@stackup/form</h1>

<div align="center">

![Build](https://github.com/rzane/form/workflows/Build/badge.svg)
![Version](https://img.shields.io/npm/v/@stackup/form)
![Size](https://img.shields.io/bundlephobia/minzip/@stackup/form)
![License](https://img.shields.io/npm/l/@stackup/form)

</div>

A type-safe approach to managing complex form state in React.

This library provides integration with [@stackup/validate](https://github.com/rzane/validate) to handle validation. However, it should be pretty easy to integrate whatever validation library you prefer.

You should also checkout [@stackup/inputs](https://github.com/promptworks/inputs), which includes some ready-made form fields.

## Usage

```jsx
import React from "react";
import { useForm, useField } from "@stackup/form";

const Form = () => {
  const form = useForm({ initialValue: { email: "", name: "" } });

  const validate = useValidation(form, value => {
    if (value.email) {
      return { valid: true, value };
    } else {
      return { valid: false, error: { email: "is required" } };
    }
  });

  const submit = useSubmit(validate, value => {
    console.log(value);
  });

  return (
    <form onSubmit={submit}>
      <Input type="email" label="Email" field={useField(form, "email")} />
      <Input type="text" label="Name" field={useField(form, "name")} />
      <button type="submit">Save</button>
    </form>
  );
};

const Input = ({
  label,
  field: { id, value, error, touched, setValue, setTouched },
  ...props
}) => (
  <div>
    <label htmlFor={id}>{label}</label>
    <input
      {...props}
      id={id}
      value={value}
      onBlur={useCallback(() => setTouched(true), [])}
      onChange={useCallback(e => setValue(e.target.value), [setValue])}
    />
    {touched && error && <p>{error}</p>}
  </div>
);
```

## API

<!-- Generated by documentation.js. Update this documentation by updating the source code. -->

#### Table of Contents

- [useForm](#useform)
- [useField](#usefield)
- [useValidation](#usevalidation)
- [useValidate](#usevalidate)
- [useSubmit](#usesubmit)
- [useReset](#usereset)
- [useFieldItem](#usefielditem)
- [usePushItem](#usepushitem)
- [useInsertItem](#useinsertitem)
- [useRemoveItem](#useremoveitem)
- [useIdentifier](#useidentifier)
- [Form](#form)
- [FormField](#formfield)
- [ValidateFn](#validatefn)
- [Submit](#submit)
- [Submission](#submission)
- [Reset](#reset)
- [UseFormOptions](#useformoptions)
- [UseValidationOptions](#usevalidationoptions)

### useForm

Create a new form. A form requires an initial value, a function to validate,
and a submit handler.

A form behaves just like any other field, but with some extra properties for
managing submission.

The initial value for the form can be literally anything! Usually, it's an
object, but it could be any type of value.

#### Parameters

- `options` **[UseFormOptions](#useformoptions)&lt;Value>**

#### Examples

Form values can be primitive

```javascript
const form = useForm({ initialValue: "" });
```

But usually, they'll contain an object

```javascript
const form = useForm({
  initialValue: {
    email: "",
    name: ""
  }
});
```

Returns **[Form](#form)&lt;Value>**

### useField

Create a field for a given property.

#### Parameters

- `field` **[FormField](#formfield)&lt;Value>**
- `name` **[Name](https://developer.mozilla.org/)**

#### Examples

```javascript
const form = useForm({
  initialValue: {
    email: "",
    profile: { name: "" } }
  }
});

const email = useField(form, "email");
const profile = useField(form, "profile");
const name = useField(profile, "name");
```

Returns **[FormField](#formfield)&lt;any>**

### useValidation

Use a plain ol' function for validation.

This hook can also be used to incorporate your favorite validation library.

#### Parameters

- `form` **[Form](#form)&lt;Value, Value>**
- `fn` **[ValidateFn](#validatefn)&lt;Value, Result>**
- `opts` **[UseValidationOptions](#usevalidationoptions)** (optional, default `{}`)

#### Examples

```javascript
const validation = useValidation(form, value => {
  if (!value.email) {
    return { valid: false, error: { email: "can't be blank" } };
  }

  return { valid: true, value };
});
```

Returns **[Form](#form)&lt;Value, Result>**

### useValidate

Add validation to the form using [@stackup/validate](https://github.com/rzane/validate).

#### Parameters

- `form` **[Form](#form)&lt;Value, Value>**
- `validator` **Validator&lt;(Value | any), Result>**
- `opts` **[UseValidationOptions](#usevalidationoptions)?**

#### Examples

```javascript
const validator = schema({
  email: assert(isString).then(refute(isBlank))
});

const validate = useValidate(form, validator);
```

Returns **[Form](#form)&lt;Value, Result>**

### useSubmit

Create a submit handler for the form.

#### Parameters

- `form` **[Form](#form)&lt;Value, Result>**
- `fn` **SubmitFn&lt;Result>**
- `opts` **ValidateOptions** (optional, default `{touch:true}`)

#### Examples

Sumbitting a form

```javascript
const form = useForm({ initialValue: "foo" });
const submit = useSubmit(form, console.log);
```

Sumbitting with validation

```javascript
const form = useForm({ initialValue: "foo" });
const validate = useValidate(form, myValidator);
const submit = useSubmit(validate, console.log);
```

Returns **[Submit](#submit)**

### useReset

Create a reset handler for the form.

#### Parameters

- `form` **[Form](#form)&lt;Value, Result>**

#### Examples

```javascript
const form = useForm({ initialValue: "foo" });
const reset = useReset(form);
```

Returns **[Reset](#reset)**

### useFieldItem

Create a field for a specific index in an array.

This hook is intended for use in building forms with "Add another" functionality.

#### Parameters

- `field` **[FormField](#formfield)&lt;[Array](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)&lt;Value>>**
- `index` **[number](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number)**

#### Examples

```javascript
const form = useForm({ initialValue: { pets: [{ name: "" }] } });
const pets = useField(form, "pets");
const pet = useFieldItem(pets, 0);
const name = useField(pet, "name");
```

Returns **[FormField](#formfield)&lt;Value>**

### usePushItem

Adds a new value to the end to an array of values.

This can be used to create a form with repeating fields.

#### Parameters

- `field` **[FormField](#formfield)&lt;[Array](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)&lt;Value>>**
- `value` **Value**

#### Examples

```javascript
const pets = useField(form, "pets");
const pet = useFieldItem(pets, 0);
const addPet = usePushItem(pets, { name: "" });
```

### useInsertItem

Adds a new value at a specific position to an array of values.

This can be used to create a form with repeating fields.

#### Parameters

- `field` **[FormField](#formfield)&lt;[Array](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)&lt;Value>>**
- `index` **[number](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number)**
- `value` **Value**

#### Examples

```javascript
const pets = useField(form, "pets");
const pet = useFieldItem(pets, 0);
const insert = useInsertItem(pets, 0, { name: "" });
```

### useRemoveItem

Removes a value at the given index from array of values.

This can be used to create a form with repeating fields.

#### Parameters

- `field` **[FormField](#formfield)&lt;[Array](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)&lt;Value>>**
- `index` **[number](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number)**

#### Examples

```javascript
const pets = useField(form, "pets");
const pet = useFieldItem(pets, 0);
const removePet = useRemoveItem(pets, 0);
```

### useIdentifier

Creates a unique identifier that will remain consistent across re-renders.

This hook does not currently support SSR.

#### Parameters

- `id` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)?**

Returns **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)**

### Form

**Extends FormField&lt;Value>**

The value returned by `useForm`.

#### initialValue

The initial values for the form.

Type: Value

#### initialError

The initial errors on the fields.

Type: FormError&lt;Value>

#### initialTouched

The initially touched fields.

Type: FormTouched&lt;Value>

#### setValidating

Indicate that the form is validating

Type: SetState&lt;[boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean)>

#### setSubmitting

Indicate that the form is validating

Type: SetState&lt;[boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean)>

#### setSubmission

Update the form's submission status

Type: SetState&lt;[Submission](#submission)>

#### reset

Reset the state of the form

Type: function (opts: ResetOptions&lt;Value>): void

#### validate

Run validation

Type: function (opts: ValidateOptions): [Promise](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Promise)&lt;ValidationResult&lt;Value, Result>>

### FormField

The primary form data structure.

#### id

A unique ID for this form field. This can be used to associate fields with a label.

Type: [string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)

#### name

The name or array index that was given to [useField](#usefield) or [useFieldItem](#usefielditem).

Type: ([string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) \| [number](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number))

#### value

The current value of the field.

Type: Value

#### error

An error or errors that are associated with this field or it's children.

Type: FormError&lt;Value>

#### touched

Indicates that this field or it's children have been modified by the user.

Type: FormTouched&lt;Value>

#### isValidating

Indicates that validation is currently being run

Type: [boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean)

#### isSubmitting

Indicates that the form is currently being submitted

Type: [boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean)

#### submission

Keeps track of the form's submission status

Type: [Submission](#submission)

#### setValue

Change the value. Just like with `setState`, you can pass a callback
to this function to get the current value and update it.

Type: SetState&lt;Value>

#### setError

Update the error.

Type: SetState&lt;FormError&lt;Value>>

#### setTouched

Indicate that this field has been touched. This is usually called in `onBlur`.

Type: SetState&lt;FormTouched&lt;Value>>

### ValidateFn

A function used for validation. This function must indicate whether
or not the form is valid.

The `error` property can be used to set errors on the form.

The `value` property can be used to transform the form's values before
validation.

Type: function (value: Value): (ValidationResult&lt;Value, Result> | PromiseLike&lt;ValidationResult&lt;Value, Result>>)

### Submit

Submits the form.

Type: function (event: FormEvent&lt;[HTMLFormElement](https://developer.mozilla.org/docs/Web/API/HTMLFormElement)>): [Promise](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Promise)&lt;void>

### Submission

Keeps track of submissions.

#### count

The number of times the form has been submitted

Type: [number](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number)

#### error

If the submission flow throws an error, it will appear here.

Type: [Error](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Error)

### Reset

Resets the form.

Type: function (event: FormEvent&lt;[HTMLFormElement](https://developer.mozilla.org/docs/Web/API/HTMLFormElement)>): [Promise](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Promise)&lt;void>

### UseFormOptions

The options that can be passed to [useForm](#useform).

#### id

Customize the base ID for all fields.

Type: [string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)

#### initialValue

The initial values for the form.

Type: Value

#### initialError

The initial errors on the fields.

Type: FormError&lt;Value>

#### initialTouched

The initially touched fields.

Type: FormTouched&lt;Value>

### UseValidationOptions

Configures when validation runs.

#### onChange

Enables validation whenever values change.

Type: [boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean)

#### onBlur

Enables validation whenever a field is touched.

Type: [boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean)