{"id":25600598,"url":"https://github.com/promotively/react-redux-form","last_synced_at":"2025-08-11T09:17:16.645Z","repository":{"id":57138264,"uuid":"169575421","full_name":"promotively/react-redux-form","owner":"promotively","description":"Universal/isomorphic react.js/redux.js library for building forms","archived":false,"fork":false,"pushed_at":"2020-10-21T01:13:25.000Z","size":2326,"stargazers_count":2,"open_issues_count":1,"forks_count":1,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-08-08T21:14:35.253Z","etag":null,"topics":["actions","async","es6","forms","higher-order-component","hoc","hooks","isomorphic","javascript","promises","react","react-redux","reactjs","redux","redux-thunk","server-side-rendering","ssr","typescript","universal"],"latest_commit_sha":null,"homepage":"https://www.promotively.com","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/promotively.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2019-02-07T13:24:29.000Z","updated_at":"2021-09-03T06:14:43.000Z","dependencies_parsed_at":"2022-08-25T10:01:23.567Z","dependency_job_id":null,"html_url":"https://github.com/promotively/react-redux-form","commit_stats":null,"previous_names":[],"tags_count":17,"template":false,"template_full_name":null,"purl":"pkg:github/promotively/react-redux-form","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/promotively%2Freact-redux-form","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/promotively%2Freact-redux-form/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/promotively%2Freact-redux-form/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/promotively%2Freact-redux-form/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/promotively","download_url":"https://codeload.github.com/promotively/react-redux-form/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/promotively%2Freact-redux-form/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":269659305,"owners_count":24455099,"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-08-09T02:00:10.424Z","response_time":111,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","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":["actions","async","es6","forms","higher-order-component","hoc","hooks","isomorphic","javascript","promises","react","react-redux","reactjs","redux","redux-thunk","server-side-rendering","ssr","typescript","universal"],"created_at":"2025-02-21T15:27:06.695Z","updated_at":"2025-08-11T09:17:16.571Z","avatar_url":"https://github.com/promotively.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# @promotively/react-redux-form\n\n[![MIT License](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n[![NPM Version](https://badge.fury.io/js/%40promotively%2Freact-redux-form.svg)](https://badge.fury.io/js/%40promotively%2Freact-redux-form)\n[![Coverage Status](https://coveralls.io/repos/github/promotively/react-redux-form/badge.svg)](https://coveralls.io/github/promotively/react-redux-form)\n[![Build Status](https://codebuild.us-west-1.amazonaws.com/badges?uuid=eyJlbmNyeXB0ZWREYXRhIjoiN3BRdWU4eHhaOU50VG9oZEhsaHJ4YmJxQWVXNmhyVUdpN21MQk0zVTNMRVQ4clFTOTA3TXdnNU5EUFFyaEUxTktnVzFkV0J4azNZZG03R3p3eFNhR0FNPSIsIml2UGFyYW1ldGVyU3BlYyI6Ikt4R0REVk5ZQlZwQnAyY3EiLCJtYXRlcmlhbFNldFNlcmlhbCI6MX0%3D\u0026branch=master)](https://aws.amazon.com/codebuild)\n[![GitHub Issues](https://img.shields.io/github/issues/promotively/react-redux-form.svg)](https://github.com/promotively/react-redux-form/issues)\n[![GitHub Pull Requests](https://img.shields.io/github/issues-pr/promotively/react-redux-form.svg)](https://GitHub.com/promotively/react-redux-form/pull/)\n\nUniversal/isomorphic react.js/redux.js javascript/typescript library for building forms.\n\n## Why?\n\n- You are using redux.js in your app.\n- You are frustrated with using redux-form and the lack of alternative solutions.\n- You need a form library that has dual API's for working with higher order components or hooks with react.js.\n- You want an easy yet powerful and performant way to build forms that closely matches building normal html forms.\n- You are building a new app and want to use redux.js to handle your form state.\n- You plan on building complicated form flows that can be difficult to accomplish without redux.js.\n- You have existing repetitive form related react.js/redux.js boilerplate that you want to refactor.\n- You want a proper form state abstraction layer but don't have the time to build one.\n- You want to be able to debug your forms through redux dev tools.\n- You need a library that is compatible with server side rendering (server side state management).\n- You want to use a library that has been extensively battle tested and built to handle all typical (and not so typical) form behaviours in modern web applications.\n- You need to handle advanced A/B testing scenarios with your forms.\n- You want to retain your form state even when a form is not rendered (ie: multi step forms)\n- You need to integrate with external applications and/or tools and need an API that is not react.js based.\n- You need to know if a form or input has been touched, changed or completed.\n- You need client side async/sync validation on a form or input(s).\n\n## Installation\n\nWith Yarn\n\n`yarn add @promotively/react-redux-form`\n\nWith NPM\n\n`npm install @promotively/react-redux-form`\n\n## Example\n\nAdvanced examples using higher order components and hooks rendered with nodejs and web browsers are available inside the `/example` folder.\n\nOnce you have executed `yarn build` go to the `dist/example` folder and from there you can open the `index.html` file to run the example.\n\nThe example is also [available online](https://promotively-react-redux-form.s3-us-west-1.amazonaws.com/example/index.html).\n\n## Documentation\n\nThe source code is documented using JSDoc syntax and documentation is generated using [jsdoc](https://github.com/jsdoc/jsdoc).\n\nOnce you have executed `yarn docs` documentation is available inside the `dist/docs` folder.\n\nDocumentation for the most recent release is also [available online](https://promotively-react-redux-form.s3-us-west-1.amazonaws.com/docs/index.html).\n\nTypeScript definitions are also available in the `dist/lib` folder.\n\n## Setup\n\nAdd `reducer` to your redux store and make sure that `redux-thunk` is also added to your store middleware.\n\n```javascript\n// store.js\n\nimport { applyMiddleware, combineReducers, createStore } from 'redux';\nimport { reducer } from '@promotively/react-redux-form';\nimport thunk from 'redux-thunk';\n\nexport const store = createStore({ form: reducer }, applyMiddleware(...[thunk]));\n```\n\n## Usage\n\nUse the provided form and input components to compose a form. (id is the only prop that is required)\n\n```javascript\n// components/login-form.js\n\nimport React from 'react';\nimport { Form, Input } from '@promotively/react-redux-form';\n\nexport const LoginForm = props =\u003e (\n  \u003cForm id={props.id}\u003e\n    \u003cInput id=\"email\" name=\"Email\" type=\"email\" /\u003e\n    \u003cInput id=\"password\" name=\"Password\" type=\"password\" /\u003e\n    \u003cbutton\u003eSubmit\u003c/button\u003e\n  \u003c/Form\u003e\n);\n```\n\n```javascript\n// app.js\n\nimport { render } from 'react-dom';\nimport { createReduxStore } from './store';\nimport { LoginForm } from 'components/login-form';\n\nconst store = createReduxStore();\n\nconst app = (\n  \u003cProvider store={store}\u003e\n    \u003cLoginForm id=\"login-form-example\" /\u003e\n  \u003c/Provider\u003e\n);\n\nrender(app, document.getElementsByTagName('main')[0]);\n```\n\n(Optional) Use custom form and input components.\n\n```javascript\n// components/custom-form.js\n\nimport React from 'react';\n\nexport const CustomForm = props =\u003e (\n  \u003cdiv\u003e\n    {props.error ? error : null}\n    \u003cform {...props} /\u003e\n  \u003c/div\u003e\n);\n```\n\n```javascript\n// components/custom-input.js\n\nimport React from 'react';\n\nexport const CustomInput = props =\u003e (\n  \u003clabel\u003e\n    \u003cspan\u003e{props.name}\u003c/span\u003e\n    \u003cinput {...props} /\u003e\n    {props.touched \u0026\u0026 props.error ? error : null}\n  \u003c/label\u003e\n);\n```\n\n```javascript\n// components/login-form.js\n\nimport React from 'react';\nimport { Form, Input } from '@promotively/react-redux-form';\nimport { CustomForm } from 'components/custom-form';\nimport { CustomInput } from 'components/custom-input';\n\nexport const LoginForm = props =\u003e (\n  \u003cForm id={props.id} component={CustomForm}\u003e\n    \u003cInput id=\"email\" name=\"Email\" type=\"email\" component={CustomInput} /\u003e\n    \u003cInput id=\"password\" name=\"Password\" type=\"password\" render={props =\u003e \u003cCustomInput {...props} /\u003e} /\u003e\n    \u003cbutton\u003eSubmit\u003c/button\u003e\n  \u003c/Form\u003e\n);\n```\n\n(Optional) Add a submission handler to the form.\n\n```javascript\n// components/login-form.js\n\nimport React from 'react';\nimport { Form, Input } from '@promotively/react-redux-form';\n\nconst handleFormSubmit = data =\u003e axios.post('http://localhost:3000/api/v1/login', data).then(response =\u003e response.data);\n\nexport const LoginForm = props =\u003e (\n  \u003cForm id={props.id} onSubmit={handleFormSubmit}\u003e\n    \u003cInput id=\"email\" name=\"Email\" type=\"email\" /\u003e\n    \u003cInput id=\"password\" name=\"Password\" type=\"password\" /\u003e\n    \u003cbutton\u003eSubmit\u003c/button\u003e\n  \u003c/Form\u003e\n);\n```\n\n(Optional) Add validation (synchronous or asynchronous) to the form.\n\n```javascript\n// component/login-form.js\n\nimport React from 'react';\nimport { Form, Input } from '@promotively/react-redux-form';\n\nconst handleFormValidation = data =\u003e {\n  if (data.email) {\n    return new Promise((resolve, reject) =\u003e {\n      if (!data.email.includes('@')) {\n        reject(new Error('email is invalid'));\n      } else {\n        resolve();\n      }\n    });\n  }\n\n  if (!data.email) {\n    return 'email is required';\n  }\n\n  if (!data.password) {\n    return 'password is required';\n  }\n};\n\nconst handleFormSubmit = data =\u003e axios.post('http://localhost:3000/api/v1/login', data).then(response =\u003e response.data);\n\nexport const LoginForm = props =\u003e (\n  \u003cForm id={props.id} validate={handleFormValidation} onSubmit={handleFormSubmit}\u003e\n    \u003cInput id=\"email\" name=\"Email\" type=\"email\" /\u003e\n    \u003cInput id=\"password\" name=\"Password\" type=\"password\" /\u003e\n    \u003cbutton\u003eSubmit\u003c/button\u003e\n  \u003c/Form\u003e\n);\n```\n\n(Optional) Disable the form when there are no changes detected or validation errors are found.\n\n```javascript\n// components/login-form.js\n\nimport React from 'react';\nimport { Form, Input } from '@promotively/react-redux-form';\n\nconst handleFormSubmit = data =\u003e axios.post('http://localhost:3000/api/v1/login', data).then(response =\u003e response.data);\n\nexport const LoginForm = props =\u003e (\n  \u003cForm id={props.id} onSubmit={handleFormSubmit}\u003e\n    \u003cInput id=\"email\" name=\"Email\" type=\"email\" /\u003e\n    \u003cInput id=\"password\" name=\"Password\" type=\"password\" /\u003e\n    \u003cbutton disabled={props.disabled}\u003eSubmit\u003c/button\u003e\n  \u003c/Form\u003e\n);\n```\n\n(Optional) Avoid destroying the form state when the component unmounts.\n\n```javascript\n// components/login-form.js\n\nimport React from 'react';\nimport { Form, Input } from '@promotively/react-redux-form';\n\nconst handleFormSubmit = data =\u003e axios.post('http://localhost:3000/api/v1/login', data).then(response =\u003e response.data);\n\nexport const LoginForm = props =\u003e (\n  \u003cForm id={props.id} onSubmit={handleFormSubmit} destroy={false}\u003e\n    \u003cInput id=\"email\" name=\"Email\" type=\"email\" /\u003e\n    \u003cInput id=\"password\" name=\"Password\" type=\"password\" /\u003e\n    \u003cbutton\u003eSubmit\u003c/button\u003e\n  \u003c/Form\u003e\n);\n```\n\n(Optional) Add validation (synchronous or asynchronous) to the inputs.\n\n```javascript\n// component/login-form.js\n\nimport React from 'react';\nimport { Form, Input } from '@promotively/react-redux-form';\n\nconst handleInputEmailValidation = (id, value) =\u003e (\n  new Promise((resolve, reject) =\u003e {\n    if (!value) {\n      reject(new Error('email is required'));\n    else if (!value.includes('@')) {\n      reject(new Error('email is invalid'));\n    } else {\n      resolve();\n    }\n  })\n);\n\nconst handleInputPasswordValidation = (id, value) =\u003e (\n  if (!value) {\n    return 'password is required';\n  }\n);\n\nexport const LoginForm = props =\u003e (\n  \u003cForm id={props.id}\u003e\n    \u003cInput id=\"email\" name=\"Email\" type=\"email\" validate={handleInputEmailValidation} /\u003e\n    \u003cInput id=\"password\" name=\"Password\" type=\"password\" validate={handleInputPasswordValidation} /\u003e\n    \u003cbutton\u003eSubmit\u003c/button\u003e\n  \u003c/Form\u003e\n);\n```\n\n(Optional) Add a default value to a input.\n\n```javascript\n// component/login-form.js\n\nimport React from 'react';\nimport { Form, Input } from '@promotively/react-redux-form';\n\nexport const LoginForm = props =\u003e (\n  \u003cForm id={props.id}\u003e\n    \u003cInput id=\"email\" name=\"Email\" type=\"email\" value=\"name@example.com\" /\u003e\n    \u003cInput id=\"password\" name=\"Password\" type=\"password\" /\u003e\n    \u003cbutton\u003eSubmit\u003c/button\u003e\n  \u003c/Form\u003e\n);\n```\n\n## API\n\n### Redux Action Creators\n\n| Function        | Arguments                                 | Description                       |\n| --------------- | ----------------------------------------- | --------------------------------- |\n| `completeForm`  | (formId)                                  | Completes a form.                 |\n| `createForm`    | (formId)                                  | Create a form.                    |\n| `errorForm`     | (formId, error)                           | Set the error state on a form.    |\n| `loadingForm`   | (formId)                                  | Sets the loading state on a form. |\n| `submitForm`    | (formId, data, action)                    | Submit a form.                    |\n| `destroyForm`   | (formId)                                  | Destroy a form.                   |\n| `resetForm`     | (formId)                                  | Reset all input values in a form. |\n| `blurInput`     | (formId, inputId)                         | Blur a input.                     |\n| `changeInput`   | (formId, inputId, defaultValue, newValue) | Change the value of a input.      |\n| `completeInput` | (formId, inputId)                         | Complete the value of a input.    |\n| `createInput`   | (formId, inputId, defaultValue)           | Create a input.                   |\n| `disableInput`  | (formId, inputId)                         | Disable a input.                  |\n| `enableInput`   | (formId, inputId)                         | Enable a input.                   |\n| `errorInput`    | (formId, inputId, error)                  | Set the error on a input.         |\n| `focusInput`    | (formId, inputId)                         | Focus a input.                    |\n| `destroyInput`  | (formId, inputId)                         | Destroy a input.                  |\n| `resetInput`    | (formId, inputId)                         | Reset an input value.             |\n\n### React Components\n\n| Function            | Arguments | Description                                                     | Props                                                                   |\n| ------------------- | --------- | --------------------------------------------------------------- | ----------------------------------------------------------------------- |\n| `FormComponent`     | (props)   | React.js component to render forms.                             | { ...HTMLFormElementProps, ...HTMLElementProps, component, render }     |\n| `InputComponent`    | (props)   | React.js component to render inputs.                            | { ...HTMLInputElementProps, ...HTMLElementProps, component, render }    |\n| `SelectComponent`   | (props)   | React.js component to render selects.                           | { ...HTMLSelectElementProps, ...HTMLElementProps, component, render }   |\n| `TextareaComponent` | (props)   | React.js component to render textareas.                         | { ...HTMLTextareaElementProps, ...HTMLElementProps, component, render } |\n| `Form`              | (props)   | React.js container component to render forms with redux.js.     | { ...HTMLFormElementProps, ...HTMLElementProps, component, render }     |\n| `Input`             | (props)   | React.js container component to render inputs with redux.js.    | { ...HTMLInputElementProps, ...HTMLElementProps, component, render }    |\n| `Select`            | (props)   | React.js container component to render selects with redux.js.   | { ...HTMLInputElementProps, ...HTMLElementProps, component, render }    |\n| `Textarea`          | (props)   | React.js container component to render textareas with redux.js. | { ...HTMLInputElementProps, ...HTMLElementProps, component, render }    |\n\n### React Higher Order Components\n\n| Function    | Arguments | Description                                 | Props                                                                                                                   |\n| ----------- | --------- | ------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------- |\n| `withForm`  | (options) | An object containing configuration options. | { ...HTMLFormElementProps, ...HTMLElementProps, touched, complete, data, touched, error, errorForm, loading, validate } |\n| `withInput` | (options) | An object containing configuration options. | { ...HTMLInputElementProps, ...HTMLElementProps, touched, complete, touched, error, focus, validate }                   |\n\n### React Hooks\n\n| Function    | Arguments | Description                                 | Props                                                                                                                      |\n| ----------- | --------- | ------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------- |\n| `useForm`  | (id, options) | An object containing configuration options. | { ...HTMLFormElementProps, ...HTMLElementProps, touched, complete, data, touched, error, errorForm, loading, validate } |\n| `useInput` | (id, options) | An object containing configuration options. | { ...HTMLInputElementProps, ...HTMLElementProps, touched, complete, touched, error, focus, validate }                   |\n\n### Redux Reducers\n\n| Function       | Description                                                                     |\n| -------------- | ------------------------------------------------------------------------------- |\n| `reducer`      | A combined redux.js reducer to handle all state mutations for forms and inputs. |\n| `formReducer`  | A redux.js reducer function to handle the state mutations for forms.            |\n| `inputReducer` | A redux.js reducer function to handle the state mutations for inputs.           |\n\n### React Redux Selectors\n\n| Function                        | Description                                                                 |\n| ------------------------------- | --------------------------------------------------------------------------- |\n| `createFormCompleteSelector`    | Create a reselect.js selector function to get the form complete state.      |\n| `createFormDirtySelector`       | Create a reselect.js selector function to get the form touched state.       |\n| `createFormDisabledSelector`    | Create a reselect.js selector function to get the form disabled state.      |\n| `createFormErrorSelector`       | Create a reselect.js selector function to get the form error state.         |\n| `createFormLoadingSelector`     | Create a reselect.js selector function to get the form loading state.       |\n| `createFormPayloadSelector`     | Create a reselect.js selector function to get the form payload.             |\n| `createFormReadySelector`       | Create a reselect.js selector function to get the form ready state.         |\n| `createFormTouchedSelector`     | Create a reselect.js selector function to get the form touched state.       |\n| `createFormValuesSelector`      | Create a reselect.js selector function to get the last form payload.        |\n| `createInputCompleteSelector`   | Create a reselect.js selector function to get the input complete state.     |\n| `createInputDirtySelector`      | Create a reselect.js selector function to get the input touched state.      |\n| `createInputDisabledSelector`   | Create a reselect.js selector function to get the input disabled state.     |\n| `createInputErrorSelector`      | Create a reselect.js selector function to get the input error state.        |\n| `createInputFocusSelector`      | Create a reselect.js selector function to get the input focus state.        |\n| `createInputReadySelector`      | Create a reselect.js selector function to get the input ready state.        |\n| `createInputRevalidateSelector` | Create a reselect.js selector function to get the input revalidation state. |\n| `createInputTouchedSelector`    | Create a reselect.js selector function to get the input touched state.      |\n| `createInputValueSelector`      | Create a reselect.js selector function to get the input value state.        |\n\n## Build\n\nAll build artifacts can be found inside the `dist/lib` and `dist/example` folders after running `yarn build`.\n\n## Linting\n\nThis library uses [@promotively/eslint-config](https://github.com/promotively/eslint-config) and [@promotively/eslint-config-react](https://github.com/promotively/eslint-config-react) for its ESLint configuration.\n\n`yarn lint`\n\n## Tests\n\nThis library has 100% unit test code coverage.\n\nCode coverage is available inside the `dist/coverage` folder after running `yarn test`.\n\nCode coverage for the most recent release is also [available online](https://promotively-react-redux-form.s3-us-west-1.amazonaws.com/tests/index.html).\n\n## Contact\n\nFeel free to reach out using any of the below methods:\n\n- [GitHub](https://github.com/promotively)\n- [FaceBook](https://facebook.com/promotively)\n- [Twitter](https://twitter.com/promotively)\n- [LinkedIn](https://linkedin.com/company/promotively)\n- [Website](https://promotively.com).\n- [Email](mailto:hello@promotively.com)\n\n## License\n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpromotively%2Freact-redux-form","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpromotively%2Freact-redux-form","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpromotively%2Freact-redux-form/lists"}