{"id":15684047,"url":"https://github.com/balazsorban44/use-form","last_synced_at":"2025-10-24T23:36:49.436Z","repository":{"id":35006096,"uuid":"195794226","full_name":"balazsorban44/use-form","owner":"balazsorban44","description":"A React hook 🎣 for easy form handling","archived":false,"fork":false,"pushed_at":"2023-05-06T06:04:01.000Z","size":2449,"stargazers_count":10,"open_issues_count":11,"forks_count":0,"subscribers_count":0,"default_branch":"master","last_synced_at":"2025-07-11T16:15:27.732Z","etag":null,"topics":["custom-hook","form","form-validation","form-validation-react","react","react-hook"],"latest_commit_sha":null,"homepage":"https://npm.im/another-use-form-hook","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/balazsorban44.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-07-08T10:58:09.000Z","updated_at":"2024-05-04T03:56:49.000Z","dependencies_parsed_at":"2024-12-10T13:44:14.558Z","dependency_job_id":"5f2eb000-ec26-493e-8fe4-9180a73e2114","html_url":"https://github.com/balazsorban44/use-form","commit_stats":{"total_commits":186,"total_committers":1,"mean_commits":186.0,"dds":0.0,"last_synced_commit":"6ee27c3deef600b5abcadd59e3e030af486fa42a"},"previous_names":[],"tags_count":47,"template":false,"template_full_name":null,"purl":"pkg:github/balazsorban44/use-form","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/balazsorban44%2Fuse-form","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/balazsorban44%2Fuse-form/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/balazsorban44%2Fuse-form/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/balazsorban44%2Fuse-form/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/balazsorban44","download_url":"https://codeload.github.com/balazsorban44/use-form/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/balazsorban44%2Fuse-form/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":266552321,"owners_count":23947172,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-07-22T02:00:09.085Z","response_time":66,"last_error":null,"robots_txt_status":null,"robots_txt_updated_at":null,"robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["custom-hook","form","form-validation","form-validation-react","react","react-hook"],"created_at":"2024-10-03T17:10:11.280Z","updated_at":"2025-10-24T23:36:49.374Z","avatar_url":"https://github.com/balazsorban44.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cdiv align=\"center\"\u003e\n\u003ch1\u003eanother-use-form-hook\u003c/h1\u003e\n\n\u003cp\u003eA React hook 🎣 for easy form handling\u003c/p\u003e\n\n\u003c/div\u003e\n\n---\n\n\n[![Build Status][build-badge]][build] [![Code Coverage][coverage-badge]][coverage] [![version][version-badge]][package] [![downloads][downloads-badge]][npmtrends] [![Total downloads][total-downloads]][total-downloads] [![MIT License][license-badge]][license] [![PRs Welcome][prs-badge]][prs] [![Code of Conduct][coc-badge]][coc]\n\n[![Watch on GitHub][github-watch-badge]][github-watch] [![Star on GitHub][github-star-badge]][github-star]\n\n---\n\n## Table of Contents\n\n- [Table of Contents](#table-of-contents)\n- [Installation](#installation)\n- [Usage](#usage)\n- [Documentation](#documentation)\n  - [useForm](#useform)\n    - [UseFormParams](#useformparams)\n      - [InitialState](#initialstate)\n      - [Validators](#validators)\n        - [Validations](#validations)\n      - [SubmitCallback](#submitcallback)\n      - [NotifyCallback](#notifycallback)\n    - [UseFormReturn](#useformreturn)\n      - [FieldValuesAndErrors](#fieldvaluesanderrors)\n      - [ChangeHandler](#changehandler)\n      - [SubmitHandler](#submithandler)\n      - [InputPropGenerators](#inputpropgenerators)\n        - [InputTypeOptions](#inputtypeoptions)\n        - [InputPropGeneratorsReturn](#inputpropgeneratorsreturn)\n  - [FormProvider](#formprovider)\n    - [FormProviderProps](#formproviderprops)\n  - [getForms](#getforms)\n    - [Forms](#forms)\n- [LICENSE](#license)\n\n\n## Installation\nThis should be installed as one of your project `dependencies`:\n\n```\nyarn add another-use-form-hook\n```\nor\n```\nnpm install --save another-use-form-hook\n```\n\n\u003e NOTE: `another-use-form-hook` only works with [**react \u003e=16.8**][react-hooks], since it is a hook.\n\n## Usage\n\nThis hook is intended to give a full solution for handling forms. From interdependent field value validations (meaning if a field value is dependent on other field value), to submitting the form, and providing information about when the UI should be unresponsive (loading of some kind of async-like operation), in addition to notification \"hooks\" to be able to inform the users the most efficient way.\n\nTo retrieve props for an input field, you have the following options:\n 1. Using the `form.inputs.{inputType}('name')` input prop generator function (`inputTypes` is one of [these][input-types-mdn])\n 2. Using `form.fields.{name}.{value|error}` and `form.handleChange` functions\n\n\u003e NOTE: The example below is available live at [CodeSandbox][codesandbox-example]\n\u003e\nLet's see a complex example to understand how it works:\n\n```jsx\nimport React from \"react\";\nimport ReactDOM from \"react-dom\";\nimport useForm from \"another-use-form-hook\";\nimport \"./styles.css\";\n/**\n * NOTE: We are using date-fns for this example,\n * but it is absolutly not a requirement.\n */\nimport { addDays, isAfter, differenceInDays, parseISO } from \"date-fns\";\nconst isValidEmail = email =\u003e /\\w*@\\w*\\.\\w*/.test(email); // Do better 💩\n\nconst TODAY = new Date();\n\nconst App = () =\u003e {\n  const form = useForm({\n    initialState: {\n      email: \"\",\n      arrival: TODAY,\n      departure: TODAY\n    },\n    validators: (fields, isSubmitting) =\u003e ({\n      // if not submitting, don't throw errors for invalid e-mail, like an empty field\n      email: isSubmitting\n        ? isValidEmail(fields.email)\n        : typeof fields.email === \"string\",\n      // earliest arrival must be tomorrow\n      arrival: isAfter(parseISO(fields.arrival), TODAY),\n      // earliest departure must be after tomorrow\n      departure: isAfter(addDays(parseISO(fields.departure), 1), TODAY),\n      // departure must be at least a day after arrival\n      minOneNight: isSubmitting\n        ? differenceInDays(\n            parseISO(fields.departure),\n            parseISO(fields.arrival)\n          ) \u003e= 1\n        : true\n    }),\n    onNotify: (type, reason) =\u003e {\n      // you can use type and reason to send specific notifications to the user\n      switch (type) {\n        case \"submitError\":\n          console.error(\"Form could not be submitted: \", reason);\n          break;\n        case \"submitSuccess\":\n          console.info(\"Form has been submitted.\", reason);\n          break;\n        case \"validationErrors\":\n          console.warn(\n            \"The following problems occurred while validating: \",\n            reason\n          );\n          break;\n        default:\n          break;\n      }\n    },\n    onSubmit: async ({ fields, setLoading, notify }) =\u003e {\n      try {\n        setLoading(true);\n        // submitting the form, eg.: fetch(\"path/to/my/submit\")\n        const response = await new Promise(resolve =\u003e {\n          setTimeout(() =\u003e {\n            console.log(\"Submitting: \", fields);\n            resolve(fields);\n          }, 1000);\n        });\n        notify(\"submitSuccess\", response);\n      } catch (error) {\n        notify(\"submitError\", error.message);\n      } finally {\n        setLoading(false);\n      }\n    }\n  });\n\n  return (\n    \u003cform onSubmit={form.handleSubmit}\u003e\n      {/* option 1 (control all the props with a one-liner)*/}\n      \u003cfieldset\u003e\n        \u003clegend\u003eOption 1\u003c/legend\u003e\n\n        \u003clabel htmlFor=\"email\"\u003e\n          {form.fields.email.error ? \"Invalid\" : \"\"} email\n        \u003c/label\u003e\n        \u003cinput {...form.inputs.email(\"email\")} /\u003e\n\n        \u003clabel htmlFor=\"departure\"\u003e\n          {form.fields.arrival.error ? \"Invalid\" : \"\"} arrival\n        \u003c/label\u003e\n        \u003cinput\n          {...form.inputs.date(\"arrival\")}\n          // You can override props by simply defining them last\n          onChange={e =\u003e form.handleChange(e, [\"minOneNight\"])}\n        /\u003e\n      \u003c/fieldset\u003e\n\n      {/* option 2 specify id, type, name, value props manually*/}\n      \u003cfieldset\u003e\n        \u003clegend\u003eOption 2\u003c/legend\u003e\n        \u003clabel htmlFor=\"arrival\"\u003e\n          {form.fields.arrival.error ? \"Invalid\" : \"\"} arrival\n        \u003c/label\u003e\n        \u003cinput\n          type=\"date\"\n          id=\"arrival\"\n          name=\"arrival\"\n          value={form.fields.arrival.value}\n          onChange={e =\u003e form.handleChange(e, [\"minOneNight\"])}\n        /\u003e\n\n        \u003clabel htmlFor=\"departure\"\u003e\n          {form.fields.departure.error ? \"Invalid\" : \"\"} departure\n        \u003c/label\u003e\n        \u003cinput\n          type=\"date\"\n          id=\"departure\"\n          name=\"departure\"\n          value={form.fields.departure.value}\n          onChange={e =\u003e form.handleChange(e, [\"minOneNight\"])}\n        /\u003e\n      \u003c/fieldset\u003e\n\n      {/* also from option 1 */}\n      \u003cbutton {...form.inputs.submit()} disabled={form.loading}\u003e\n        Submit\n      \u003c/button\u003e\n    \u003c/form\u003e\n  );\n};\n\nReactDOM.render(\u003cApp /\u003e, document.querySelector(\"#root\"));\n```\n\n## Documentation\n\n### useForm\n\n```ts\n  useForm(useFormParams: UserFormParams): UseForm\n```\n\n#### UseFormParams\n\n| name         | type       |                                                          description |\n| :----------- | :--------- | -------------------------------------------------------------------: |\n| name         | `string`   | Refer to one of the forms in [formProviderProps](#formproviderprops) |\n| initialState | `object`   |                                    See [InitialState](#initialstate) |\n| validators   | `function` |                                        See [Validators](#validators) |\n| onSubmit     | `function` |                                See [SubmitCallback](#submitcallback) |\n| onNotify     | `function` |                                See [NotifyCallback](#notifycallback) |\n\n##### InitialState\nAn object containing the default value of every field in a form.\n\u003e Example:\n```js\nuseForm({\n  initialState: {\n    email: \"\",\n    name: \"\",\n    address: \"\",\n    age: 0\n  }\n})\n```\n\nIf `name` is defined, you can refer to `initialStates.{name}` in [formProviderProps](#formproviderprops).\n\n\u003e Example:\n```jsx\n//...\n\u003cFormProvider \n  initialStates={{\n    login: {\n      email: \"email@example.com\",\n      password: \"\"\n    }\n  }}\n\u003e\n//...\nconst form = useForm({name: \"login\"})\nconsole.log(form.fields.email.value) // email@example.com\n```\n\n##### Validators\nThis function is invoked before [onChange](#changecallback) and [onSubmit](#submitcallback). The former only runs the validations for the changed fields, while the latter runs it on the whole form. For convenience, it is also returned from `useForm`.\n```ts\nfunction validators(fields: object, isSubmitting: boolean): Validations\n```\n\n| name        | type      |                                                      description |\n| :---------- | :-------- | ---------------------------------------------------------------: |\n| fields      | `object`  |   An object with the same shape as [initialState](#initialstate) |\n| submitting  | `boolean` | Set to `true`, when called before [handleSubmit](#submithandler) |\n| validations | `object`  |                                  See [Validations](#validations) |\n\n###### Validations\nAn object containing `boolean` expressions. Each input field must have at least a corresponding property in this object, but you can define custom ones as well.\n\u003e Example:\n```js\n{\n  email: submitting\n    ? isValidEmail(fields.email)\n    : typeof fields.email === \"string\"\n}\n```\nYou can also look at the [live example](#usage).\n\n\n##### SubmitCallback\nInvoked when [handleSubmit](#submithandler) is called and there were no validation issues.\n\n```ts\nfunction onSubmit(onSubmitParams: OnSubmitParams): void\n```\n\n\n| name       | type       |                                                       description |\n| :--------- | :--------- | ----------------------------------------------------------------: |\n| name       | `string`   |                 Same as `name` in [useFormParams](#useformparams) |\n| fields     | `object`   |     Validated fields, same shape as [initialState](#initialstate) |\n| setLoading | `function` | Sets the returned `loading` property of [useForm](#useformreturn) |\n| notify     | `function` |                             See [NotifyCallback](#notifycallback) |\n\n##### NotifyCallback\nInvoked if there is a validation error when calling `handleChange` or `handleSubmit`. Can be manually triggered on `onSubmit` by calling `notify`.\n\n```ts\ntype NotifyType = \"validationErrors\" | \"submitError\" | \"submitSuccess\"\nfunction notify(type: NotifyType, reason: any): void\n```\n\n| name   | type     |                                                                                              description |\n| :----- | :------- | -------------------------------------------------------------------------------------------------------: |\n| type   | `string` |                                                                                     Type of notification |\n| reason | `any`    | When type is `validationErrors`, it is a list of field names, Otherwise you set it to whatever you want. |\n\n\u003e Example:\n\nLook at the [live example](#usage).\n\n\n#### UseFormReturn\n\n| name         | type       |                                                                   description |\n| :----------- | :--------- | ----------------------------------------------------------------------------: |\n| name         | `string`   |                                   Same as in [useFormParams](#useformparams). |\n| fields       | `object`   |                             See [FieldValuesAndErrors](#fieldvaluesanderrors) |\n| hasErrors    | `boolean`  | For convenience. `true` if any of the returned fields.{name}.error is `true`. |\n| handleChange | `function` |                                           See [ChangeHandler](#changehandler) |\n| handleSubmit | `function` |                                           See [SubmitHandler](#submithandler) |\n| loading      | `boolean`  |                     Controlled by `setLoading` in [onSubmit](#submitcallback) |\n| inputs       | `object`   |                               See [InputPropGenerators](#inputpropgenerators) |\n| validators   | `function` |                                                 See [Validators](#validators) |\n\n##### FieldValuesAndErrors\nValidated field values and their errors.\n\u003e Example:\n\n```js\n  const form = useForm({initialState: {\n    email: \"email@example.com\",\n    age: -2\n  }})\n  console.log(form.fields)\n  // {\n  //  email: {\n  //   value: \"email@example.com\",\n  //   error: false\n  //  },\n  //  age: {\n  //   value: -2,\n  //   error: truefields\n  //  }\n  // }\n  console.log(form.hasErrors) // true\n```\n##### ChangeHandler\nYou can call this two ways. Either pass an event as the first argument, or a partial `fields` object. With the latter, you can change multiple values at the same time. E.g.: resetting the form after submit, or any other reason you might have.\n```ts\nfunction handleChange(event: React.FormEvent, validations: string[]): void\nfunction handleChange(fields: object, validations: string[]): void\n```\n| name        | type              |                                                                                                      description |\n| :---------- | :---------------- | ---------------------------------------------------------------------------------------------------------------: |\n| event       | `React.FormEvent` |                                     Standard event. Using `target.{name\\|value\\|checked}` to infer the intention |\n| fields      | `object`          |                           Pass a partial `fields` object, if you want to change multiple values at the same time |\n| validations | `string[]`        | Which `validators` you would like to run. If omitted, only validators with the same event/field name will be run |\n\n\u003e Example:\n\nLook at the [live example](#usage).\n\n##### SubmitHandler\nCall to submit the form. Before [onSubmit](#submitcallback) is invoked, [validators](#validators) is run for every form field. If there were any errors, [notify](#notifycallback) is invoked with `type` being `validationErrors`, and `reason` a list of form field names.\n\n```ts\nfunction handleSubmit(): void\n```\n\n\n##### InputPropGenerators\n\nAn object, containing properties with the same name as the [HTML input types][input-types-mdn], with some minor differences. \n\nFor convenience, since `datetime-local` contains a hyphen (-) character, it is also exposed as `datetimeLocal`, to overcome the need of `\"` characters, when accessing it.\nI.e.:\n```js\nconst form = useForm()\nform.inputs.datetimeLocal == form.inputs[\"datetime-local\"]\n```\nIn addition to the standard input types, there is a `select` type also available.\n\nEach property is a function:\n\n```ts\nfunction inputType(name: string, options: InputTypeOptions): InputPropGeneratorsReturn\n```\n\n| name    | type     |                                                                  description |\n| :------ | :------- | ---------------------------------------------------------------------------: |\n| name    | `string` | The name of a field. Same as the properties of [initialState](#initialstate) |\n| options | `object` |                                    See [InputTypeOptions](#inputtypeoptions) |\n\n\u003e Example:\n\nFor examples of all types, you can check [this test suite][input-prop-generator-test-file]\n\n###### InputTypeOptions\nAn optional object\n\n| name          | type       |                                                                                                                          description |\n| :------------ | :--------- | -----------------------------------------------------------------------------------------------------------------------------------: |\n| value         | `string`   |                     Usually, when using radio buttons, values are static. (Each button in the same group must have different values) |\n| generateProps | `function` | Provides `name`, `value` and `error` that can be used to generate additional props. Useful, if you want to avoid using `form.fields` |\n| formName      | `string`   |                                      If the input type is `submit`, it can be used to override the name of the form being submitted. |\n\n\u003e Example:\n1. \n```jsx\nconst form = useForm(/*...*/)\n// *click on option-2*\nconsole.log(form.fields.radio.value) // option-2\nreturn (\n  \u003cradiogroup\u003e\n    \u003cinput {...inputs.radio('radio', { value: 'option-1' })}/\u003e\n    \u003cinput {...inputs.radio('radio', { value: 'option-2' })}/\u003e\n    {/*You can do it the \"traditional\" way also*/}\n    \u003cinput\n      {...inputs.radio('radio')} \n      value='option-3'\n    /\u003e\n  \u003c/radiogroup\u003e\n)\n```\n2. \n```jsx\nconst form = useForm(/*...*/)\nreturn(\n  \u003cdiv\u003e\n    \u003cinput\n      {...form.inputs.email(\"emailField\", {\n        generateProps: ({error}) =\u003e ({\n          className: error ? \"email-error\" : \"email\",\n        })\n      })}\n    /\u003e\n    {/*Tip: if your custom Input component takes an error prop, you can try this: */}\n    \u003cInput {...form.inputs.email(\"emailField\", {generateProps: _ =\u003e _})}/\u003e\n    {/* This will spread error to Input as well.*/}\n\n    {/*Or here is a more complex example for a custom Input component*/}\n    \u003cInput \n      {...form.inputs.email(\"emailField\", {\n        generateProps: ({error, name}) =\u003e ({\n          error,\n          label: error ? `Invalid ${name}` : name,\n          placeholder: `Type ${name}`\n        })\n      })}\n    /\u003e\n  \u003c/div\u003e\n)\n```\n\n\n###### InputPropGeneratorsReturn\nAn object that can be spread on a React input like element.\n\n| name     | type       |                                                                                                                                     description |\n| :------- | :--------- | ----------------------------------------------------------------------------------------------------------------------------------------------: |\n| name     | `string`   |                                                             The name of a field. Must be one of the properties in [initialState](#initialstate) |\n| id       | `string`   | By default, same as `name`. If input type is `radio`, it is the same as `value`, to avoid problems in radio groups where `id` would be the same |\n| value    | `any`      |                                                                                                                          The value of the field |\n| onChange | `function` |                                                                                                                  See [onChange](#changehandler) |\n| checked  | `boolean`  |                                                                                          If input type is `checkbox`, it is the same as `value` |\n| onClick  | `function` |                                                                                     If input type is `submit`, it is [onSubmit](#submithandler) |\n\n\u003e Example:\n\n```jsx\nconst form = useForm(/*...*/)\n\nreturn (\n  \u003cdiv\u003e\n    \u003clabel htmlFor=\"emailField\"\u003eE-mail\u003c/label\u003e\n\n    \u003cinput {...form.inputs.email(\"emailField\")}/\u003e\n    {/* This is the same as */}\n    \u003cinput\n      name=\"emailField\"\n      id=\"emailField\"\n      type=\"email\"\n      onChange={form.handleChange}\n      value={form.fields.emailField.value}\n    /\u003e\n  \u003c/div\u003e\n)\n```\n\n### FormProvider\n\n```ts\n  function FormProvider(formProviderProps: FormProviderProps): JSX.Element\n```\n\n#### FormProviderProps\n\n| name          | type           |                                                                                 description |\n| :------------ | :------------- | ------------------------------------------------------------------------------------------: |\n| initialStates | `object`       | Single place to define all `initialState` for every form. See [InitialState](#initialState) |\n| validators    | `object`       |      Single place to define all `validators` for every form. See  [Validators](#validators) |\n| onSubmit      | `function`     |                                                         Same as [onSubmit](#submitcallback) |\n| onNotify      | `function`     |                                                         Same as [onNotify](#notifycallback) |\n| children      | `ReactElement` |                                      The element you would like to wrap with `FormProvider` |\n\n\n\n### getForms\n```ts\n  function getForms() : Forms\n```\n\n#### Forms\nAn object containing all the forms' current values in [FormProvider](#formprovider). Same shape as `initialStates`.\n\n\n---\n\n## LICENSE\n\nMIT\n\n[build-badge]:\n  https://img.shields.io/travis/balazsorban44/use-form.svg?style=flat-square\n[build]: https://travis-ci.org/balazsorban44/use-form\n[coverage-badge]:\n  https://img.shields.io/codecov/c/github/balazsorban44/use-form.svg?style=flat-square\n[coverage]: https://codecov.io/github/balazsorban44/use-form\n[version-badge]:\n  https://img.shields.io/npm/v/another-use-form-hook.svg?style=flat-square\n[package]: https://www.npmjs.com/package/another-use-form-hook\n[downloads-badge]:\n  https://img.shields.io/npm/dm/another-use-form-hook.svg?style=flat-square\n\n[npm]: https://www.npmjs.com/\n[node]: https://nodejs.org\n\n[npmtrends]: http://www.npmtrends.com/another-use-form-hook\n[license-badge]:\n  https://img.shields.io/npm/l/another-use-form-hook.svg?style=flat-square\n[license]:\n  https://github.com/balazsorban44/use-form/blob/master/LICENSE\n[prs-badge]:\n  https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square\n[prs]: http://makeapullrequest.com\n[donate-badge]:\n  https://img.shields.io/badge/$-support-green.svg?style=flat-square\n[coc-badge]:\n  https://img.shields.io/badge/code%20of-conduct-ff69b4.svg?style=flat-square\n[coc]:\n  https://github.com/balazsorban44/use-form/blob/master/CODE_OF_CONDUCT.md\n[github-watch-badge]:\n  https://img.shields.io/github/watchers/balazsorban44/use-form.svg?style=social\n[github-watch]: https://github.com/balazsorban44/use-form/watchers\n[github-star-badge]:\n  https://img.shields.io/github/stars/balazsorban44/use-form.svg?style=social\n[github-star]: https://github.com/balazsorban44/use-form/stargazers\n[react-hooks]: https://reactjs.org/blog/2019/02/06/react-v16.8.0.html\n[input-types-mdn]: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input\n[codesandbox-example]: https://codesandbox.io/s/another-use-form-hook-2mler\n[input-prop-generator-test-file]: https://github.com/balazsorban44/use-form/blob/master/src/__tests__/useForm-with-input-prop-generator.test.js\n[total-downloads]: https://img.shields.io/npm/dt/another-use-form-hook.svg?label=total%20downloads\u0026style=flat-square\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbalazsorban44%2Fuse-form","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbalazsorban44%2Fuse-form","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbalazsorban44%2Fuse-form/lists"}