
Product
Introducing Repository Access Permissions and Custom Roles
Socket now supports Custom Roles and Repository Access Permissions so organizations can control who can access specific repositories and actions.
yet-another-form
Advanced tools
Yet another form-state management library. There are a bunch of them. This one is another take on this problem.
size-limit to check the size of the library after each commit.Install the yet-another-form
# npm
npm install yet-another-form
#yarn
yarn add yet-another-form
#pnpm
pnpm add yet-another-form
Import useForm hook into yor component
import { useForm } from 'yet-another-form/react'
const AddUser = ({ onAddUser }) => {
const { Form, setValue, values } = useForm({ onSubmit: onAddUser })
return (
<Form>
<input name="name" onChange={setValue} value={values.name} />
<input name="email" onChange={setValue} value={values.email} />
<button>Add user</button>
</Form>
)
}
yet-another-form supports form-level and field-level validations.
To validate on the form-level, you need to pass a validate function with the form config. This function will receive the latest form values and should return either an object with errors, or the promise, that resolves to that object, or something in between:
validate(values) {
return {
name: values.name ? undefined : 'name is required',
email: values.email ? undefined : 'email is required',
}
}
validate(values) {
return validateUserDataOnServer(values)
}
isValidating property of form status will be set to true and isValid will be set to falsevalidate(values) {
return {
name: values.name ? undefined : 'name is required',
email: validateEmailOnServer(values.email)
}
}
isValidating properties will be set to true and isValid properties will be falseForm-level validation runs on each change. But it can be debounced through the debounce property in the form config (ms).
For field-level validation, you can pass a validate function (sync or async) to the useFormField hook config. The function will receive the field value as the first argument and the latest form values as the second.
When the form is submitted, a few things happen:
isSubmitting flag to trueonSubmit handler, it will call it, with form values, and a "bag" with form status and reset methodisSubmitting flag will be set to falseonSubmit handler, it will fall back to default browser behavior for the <form> element, i.e., form data will be sent to the provided endpoint, and the browser will reload the page.useFormThe useForm is the main hook that creates and configures the form store.
const formContext = useForm(config)
debounceValidation: number — if set, then form validation will happen only once within the defined period
initialValues: any — default values for the form
if initialValues changes, the form will be reset. Previous and next values are compared deeply, so you don't need to memorize those (use useMemo), but the latter might improve performance.
onSubmit(values, formBag) => Promise<void> | void — submit handler. Is called when form is submitted: either the HTML <form> element is submitted, or formContext.submit is called.
formBag – is an object with a few helpful props and methods:
isDirty: boolean — indicates whether any field was changed or not
isValid: boolean — indicates whether the form has any errors or not
dirtyFields: string[] — list of fields that had been changed - errorFields: string[] — list of fields that have errors
errorFields: string[] — list of fields that have errors
validatingFields: string[] — list of fields that are validating (in case of async validation)
reset() => void — resets the form and sets submitted values as default values
validate(values) => any | Promise<any> validation function. It will receive form values and should return an object that contains errors for fields. More about validation
useForm hook returns an object with the current form state and several helpers and setters to update the form state.
Form: ReactComponent — thin wrapper around HTML <form> element. It wraps <form> into form context provider, and "binds" its onSubmit handler with the form store
<Form> component will be passed to the underlying <form> element, even onSubmit<Form> forwards the ref to the underlying <form> element, so you can pass react refs to itisDirty: boolean — indicates whether any field was changed or notisSubmitting: boolean — indicates whether the form is submitting dataisValid: boolean — indicates whether the form has any errors or notdirtyFields: string[] — list of fields that had been changed
useForm hook, the react component will not be updated, if it changeserrorFields: string[] — list of fields that have errors
useForm hook, the react component will not be updated, if it changesvalidatingFields: string[] — list of fields that are validating (in case of async validation)
useForm hook, the react component will not be updated, if it changesformContext: FormContext — a form store, in case you need to pass it to other hooks manuallysetError: function — sets error for the form or a particular field
(fieldPath: string, error: string | undefined) => void(fieldPath: string, error: Promise<string | undefined>) => void(fieldPath: string) => (error: string | undefined) => void(fieldPath: string) => (error: Promise<string | undefined>) => voiduseEffect or useCallbacksetTouched: function — sets whether particular field or fields were touched or not
(event: BlurEvent) => void(fieldPath: string, touched: boolean) => void(fieldPath: string) => (touched: boolean) => void(fieldPath: string) => (event: BlurEvent) => voidonBlur handler. In this case, will set the touched value to true when input loses focususeEffect or useCallbacksetValue: function — sets value for the form or a particular field
(event: ChangeEvent) => void(event: ChangeEvent) => void(fieldPath: string, value: any) => void(fieldPath: string) => (event: ChangeEvent) => void(fieldPath: string) => (value: any) => voidonChange handler. In this case, it will try to read the field path from the input nameuseEffect or useCallbackreset(initialValues?: any) => void — resets the form to its initial values
submit() => void — submits the formuseFormFieldThe useFormField hook is used to get data and setters for a particular field. It should be used within form context (in a sub-tree of the Form component, returned by the useForm hook).
If you want to use the useFormField hook in the same code block as the useForm and not in the <Form> sub-tree, you need to pass the FormContext to the hook as part of the hook config.
const field = useFormField('address.city')
// or with manually passed form context
const { formContext } = useForm()
const field = useFormField('address', { formContext })
path: string— the path of a particular field in the form state
address.city or items[0].titleconfig — optional hook config
formContext: FormContext — form context
useFormField hook is used outside form context provider, you need to manually pass form context as a second argumentvalidate(value: any, formValues: any) => string | undefined | Promise<string | undefined> — field-level validation functionuseFormField hook returns an object with the current field state and several setters to update a field.
error: string | undefined — field error, if anyisDirty: boolean — indicates whether the field was changed or notisValidating: boolean — indicates whether the field is being validatedtouched: boolean — indicates whether the field was touchedvalue: any — field valuesetError(error: string | undefined | Primise<string | undefined> – sets error for the field
useEffect or useCallbacksetTouched(touched: boolean | BlurEvent) => — sets whether the field was touched or not
onBlur handler. In this case, will set the touched value to true, when input loses focususeEffect or useCallbacksetValue(value: any | ChangeEvent) => void — sets value for the field
onChange handleruseEffect or useCallbackuseFormStateThe useFormState hook returns a form state. It should be used within form context (in a sub-tree of the Form component, returned by the useForm hook).
If you want to use the useFormState hook in the same code block as the useForm and not in the <Form> sub-tree, you need to pass the FormContext to the hook as its first argument.
const formState = useFormState()
// or with manually passed form context
const { formContext } = useForm()
const formState = useFormState(formContext)
formContext: FormContext — form context
useFormState hook is used outside form context provider, you need to manually pass form context to ituseFormState hook returns an object with the current form state.
isDirty: boolean — indicates whether any field was changed or notisSubmitting: boolean — indicates whether the form is submitting dataisValid: boolean — indicates whether the form has any errors or notdirtyFields: string[] — list of fields that had been changed
useForm hook, the react component will not be updated, if it changeserrorFields: string[] — list of fields that have errors
useForm hook, the react component will not be updated, if it changesvalidatingFields: string[] — list of fields that are validating (in case of async validation)
useForm hook, the react component will not be updated, if it changesPart of the code, typings and API design was inspired by other form state management libraries:
FAQs
Form state management library
We found that yet-another-form demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Product
Socket now supports Custom Roles and Repository Access Permissions so organizations can control who can access specific repositories and actions.

Product
Socket MCP now lets AI assistants review org alerts, investigate threats using the Socket threat feed, and inspect package files in addition to dependency scoring.

Product
Socket Firewall blocks malicious VS Code and Open VSX extensions before install, protecting developers from compromised editor marketplaces.