{"id":25760415,"url":"https://github.com/j0nas/light-form","last_synced_at":"2025-02-26T18:19:41.039Z","repository":{"id":75898610,"uuid":"89852179","full_name":"j0nas/light-form","owner":"j0nas","description":"Lightweight library for lightweight React/Redux forms","archived":false,"fork":false,"pushed_at":"2017-07-06T20:01:30.000Z","size":167,"stargazers_count":37,"open_issues_count":0,"forks_count":4,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-02-12T01:41:56.157Z","etag":null,"topics":["abstraction","form","react","redux","redux-form","state","state-management"],"latest_commit_sha":null,"homepage":"http://light-form.surge.sh","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/j0nas.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"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":"2017-04-30T13:23:59.000Z","updated_at":"2023-10-20T08:24:31.000Z","dependencies_parsed_at":null,"dependency_job_id":"8284e3a1-e4d6-4db9-a0d3-fe6624f68339","html_url":"https://github.com/j0nas/light-form","commit_stats":{"total_commits":151,"total_committers":3,"mean_commits":"50.333333333333336","dds":0.152317880794702,"last_synced_commit":"38578824e9c9bf1004763d61707f539259f1965f"},"previous_names":[],"tags_count":6,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/j0nas%2Flight-form","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/j0nas%2Flight-form/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/j0nas%2Flight-form/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/j0nas%2Flight-form/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/j0nas","download_url":"https://codeload.github.com/j0nas/light-form/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":240226236,"owners_count":19768052,"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","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":["abstraction","form","react","redux","redux-form","state","state-management"],"created_at":"2025-02-26T18:19:40.354Z","updated_at":"2025-02-26T18:19:41.028Z","avatar_url":"https://github.com/j0nas.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"Light-form\n=========================\n\u003e Lightweight library for boilerplate-free React/Redux forms\n\n[![CircleCI](https://circleci.com/gh/j0nas/light-form/tree/master.svg?style=shield)](https://circleci.com/gh/j0nas/light-form/tree/master)\n[![Coverage Status](https://coveralls.io/repos/github/j0nas/light-form/badge.svg)](https://coveralls.io/github/j0nas/light-form)\n\n**light-form** is a lightweight library that lets you create boilerplate-free React/Redux.\n\nCheck out the [live demo][surge] and the [examples]. \n\n## Installation\n```\nnpm install --save light-form  \n```\n\n## Example\n```jsx harmony\n// CustomerForm.jsx\nimport React from 'react';\nimport {Input} from 'light-form';\n\nconst CustomerForm = () =\u003e\n  \u003cdiv\u003e\n    \u003cInput name=\"customer.firstname\" /\u003e\n    \u003cInput name=\"customer.lastname\" /\u003e\n  \u003c/div\u003e;\n    \nexport default CustomerForm;\n```\n\nImport `Reducer` and pass it the name which you alias the reducer to. This should be the same\nas the first part of the dot-delimited `name` property for the fields in your form.\nThen add the reducer to your store setup (eg. using ``combineReducers``).\n```jsx harmony\n// rootReducer.js\nimport {combineReducers} from 'redux';\nimport {Reducer} from 'light-form';\n\nconst rootReducer = combineReducers({\n  customer: Reducer('customer'),\n  // .. other reducers\n});\n\nexport default rootReducer;\n```\n\n## Quick start\n**light-form** only requires four simple steps to get started:\n* in your view, `import {Input, Select, TextArea} from \"light-form\";`\n* pass the components a `name` prop in the form of `[formName].[fieldName]`\n  * (eg. `\u003cInput name=\"myForm.myField\" /\u003e`)\n* in your root reducer, `import {Reducer} from \"light-form\";` \n* pass it `[formName]` and add it to your store under the same name  \n  * (eg. `combineReducers({ myForm: Reducer('myForm'), ... })`)\n\nAnd that's it, your form is ready!\n\n## How it works\n**light-form** exports `\u003cInput /\u003e`, `\u003cSelect /\u003e` and `\u003cTextArea /\u003e` components.\nThese components come with `value` and `onChange` props attached under the hood.\nThose props are wired up to the reducer with the matching name, eg. `customer` in the \nexample above. So entering 'Jonas' and 'Jensen' into the example form above would give \nus this state tree:\n```js\n{\n  customer: {\n    firstname: 'Jonas',\n    lastname: 'Jensen'\n  }\n}\n```\n\nThe components' `value` prop is handled in the reducer and should never be explicitly set. \nThe `onChange` prop is intercepted by the components' container, if defined. See 'Defining \ncustom onChange handlers' below.\n\n## Why it's useful\n**light-form** aims to combine ease of use with flexibility. The following are its strong \npoints.\n\n### Reduced boilerplate\nMapping and attaching `value` and `onChange` props is done the same way in most use cases, \nso light-form abstracts that away. The same applies for the reducer which handles those \nprops. Rather than typing out repetitive code, we can focus on the domain aspects which \nmakes our forms unique. To demonstrate this, compare the example above to the \n[equivalent][vanilla gist] form in \"vanilla\" React/Redux. This grows more beneficial with \nincreased complexity, such as with multi-part forms. See *Nested* demo/example.  \n\n### No abstraction trade-off  \nYou can opt to have complete control of the form's events. The onChange prop and the reducer \naction handler have hooks which you can use to intercept the changes and perform mutations. \nThis allows for have fine-tuned control where necessary, just like with vanilla React/Redux. \nSee *InterceptOnChange* and *OnStateChange* demo/examples.\n\n### No ad-hoc magic  \nYou can treat the provided components almost as standard \n[uncontrolled React components][uncontrolled], except they're in sync with the Redux store \nby default. Any props you pass them are applied. Eg., the provided `\u003cInput /\u003e` is just a \nwrapper for a standard `\u003cinput /\u003e`, and will accept any props that would be valid for \n`\u003cinput /\u003e`. `value` and `onChange` are the exceptions, see \"Defining custom event handlers\".\n\n## Defining custom event handlers\nThe exported components and reducer have hooks which you can pass functions to. This allows\nfor fine-grained control of the events passed to the components and the resulting state\non reducer changes.\n\n### Custom onChange handlers for fields\nIf the `onChange` prop of a field is defined, the passed function will be invoked, and the \nreturn of that function will be passed to the internal onChange function. This allows for \ncomplete control of the onChange handling and outcome. The function passed to the prop will \nreceive the event object as a parameter which you are free to copy and mutate as you please. \nReturn this event object (or a copy) as a part of the custom onChange function, or a falsy \nvalue if you want to abort handling the event. See *Intercept OnChange* example.\n\n### Custom onStateChange handler for reducer\nIn addition to an optional *defaultState* second parameter, the Reducer accepts an\n`onStateChange` function as an optional third parameter. If present, the passed function \nwill be invoked after a state update has occurred, and the function will receive the updated \nstate as a parameter. The function is free to mutate this state as needed. The function is \nexpected to return an object, which will be applied as the new state for the reducer. See \n*OnStateChange* example.\n\n### Custom reducer actions\nThe Reducer accepts an optional `actionHandlers` object as the fourth parameter. This is\nexpected to be an object with Redux action names as keys and state migration functions \n(like in conventional reducers) as values. The functions will receive `state` and `action`\nparameters, being the reducer's state and the dispatched action respectively. The value\nreturned from the function will be the new state. See *Custom reducer actions* example.\n\n[vanilla gist]: https://gist.github.com/j0nas/d597b3e7f6a6718f9c7c8ea0734d8c47\n[surge]: http://light-form.surge.sh\n[examples]: https://github.com/j0nas/light-form/tree/master/examples\n[uncontrolled]: https://facebook.github.io/react/docs/uncontrolled-components.html","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fj0nas%2Flight-form","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fj0nas%2Flight-form","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fj0nas%2Flight-form/lists"}