{"id":17133275,"url":"https://github.com/gilbox/elegant-react","last_synced_at":"2025-09-07T06:35:52.804Z","repository":{"id":33764085,"uuid":"37419707","full_name":"gilbox/elegant-react","owner":"gilbox","description":"Functional React Architecture","archived":false,"fork":false,"pushed_at":"2016-04-17T17:41:42.000Z","size":7305,"stargazers_count":62,"open_issues_count":0,"forks_count":6,"subscribers_count":6,"default_branch":"master","last_synced_at":"2025-09-07T06:35:19.561Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","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/gilbox.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":"2015-06-14T16:19:59.000Z","updated_at":"2023-09-25T23:53:06.000Z","dependencies_parsed_at":"2022-09-04T06:51:12.653Z","dependency_job_id":null,"html_url":"https://github.com/gilbox/elegant-react","commit_stats":null,"previous_names":[],"tags_count":5,"template":false,"template_full_name":null,"purl":"pkg:github/gilbox/elegant-react","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gilbox%2Felegant-react","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gilbox%2Felegant-react/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gilbox%2Felegant-react/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gilbox%2Felegant-react/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/gilbox","download_url":"https://codeload.github.com/gilbox/elegant-react/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gilbox%2Felegant-react/sbom","scorecard":{"id":426749,"data":{"date":"2025-08-11","repo":{"name":"github.com/gilbox/elegant-react","commit":"6262b22abffd48ce3942597251d621f77ee74359"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":3,"checks":[{"name":"Dangerous-Workflow","score":-1,"reason":"no workflows found","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Code-Review","score":0,"reason":"Found 1/29 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Token-Permissions","score":-1,"reason":"No tokens found","details":null,"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Pinned-Dependencies","score":-1,"reason":"no dependencies found","details":null,"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: MIT License: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 2 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}}]},"last_synced_at":"2025-08-19T02:23:41.847Z","repository_id":33764085,"created_at":"2025-08-19T02:23:41.848Z","updated_at":"2025-08-19T02:23:41.848Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":274005333,"owners_count":25205934,"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-09-07T02:00:09.463Z","response_time":67,"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":[],"created_at":"2024-10-14T19:41:48.556Z","updated_at":"2025-09-07T06:35:52.749Z","avatar_url":"https://github.com/gilbox.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# elegant-react\n\nFunctional React Architecture inspired by [omniscient](http://omniscientjs.github.io/) and [browser.html](https://github.com/mozilla/browser.html/).\nComments/suggestions/PRs are all welcome. This is still experimental.\n\nBTW, you might also find it useful to use this in conjunction with [react-derive](https://github.com/gilbox/react-derive). And check out [elegant-react-hot-demo](https://github.com/gilbox/elegant-react-hot-demo) which combines them.\n\n\n#### [Documentation](http://gilbox.github.io/elegant-react/docs/README.md.html)\n\n## what is elegant-react?\n\n`elegant-react` is an npm package. The source code for the npm package is in the `src/`\ndirectory of this repo.\n\nThis github repo is also currently the home for a growing number of experiments\nrelated to React functional patterns. The code for these experiments\nlive in the `examples/` dir. Some use the `elegant-react` npm package but others,\nfor the sake of simplicity, do not.\n\nThe `elegant-react` npm package provides:\n\n- A simple ES7 class decorator ([`@elegant-react`](https://github.com/gilbox/elegant-react/blob/master/src/create-elegant-decorator.js))\n  that via a higher-order component (HoC) facilitates working with immutable data:\n\n  * Automatically optimizes your shouldComponentUpdate. In order\n    for this optimization to be efficient, all props passed to components should be\n    scalar or immutable values. If you need to further optimize `shouldComponentUpdate`\n    you can define your own, and because the `@elegant` decorator is a HoC there's\n    no need to worry about collisions.\n\n  * Allows designated props to be treated as *static* so that changes to those\n    props don't trigger render updates.\n\n- A simple [subedit](https://github.com/gilbox/elegant-react/blob/master/src/index.js#L4) function that looks like this (if you're not using immutable-js, there are [alternatives to this `subedit` function](https://github.com/gilbox/elegant-react#dependencies)):\n\n  ```javascript\n  const subedit = (edit, ...path) =\u003e transform =\u003e\n    edit(state =\u003e state.updateIn(path, transform));\n  ```\n\n## about\n\nThis repo started off as a demonstration of some concepts that I wrote about in [this Medium article](https://medium.com/@gilbox/an-elegant-functional-architecture-for-react-faa3fb42b75b) and [this one](https://medium.com/p/7acf5d0cf00e) as well. However, since that time elegant-react\nhas continued to evolve and things have changed significantly. For the purpose of education,\nyou can check out the [elegant-react-og](https://github.com/gilbox/elegant-react) repo which\nis a copy of the elegant-react repo immediately before it began to diverge from the content\nin those two Medium articles.\n\n\n## Installation\n\nInstall via npm\n\n```bash\n  npm install elegant-react\n```\n\n## Bringing it into your project\n\nImport it:\n\n```javascript\n  import {elegant, subedit} from 'elegant-react';\n```\n\nOr if you'd like to enable debug mode:\n\n```javascript\n  import ElegantReact from 'elegant-react';\n  const {elegant, subedit} = ElegantReact({debug: true});\n```\n\nNote: the `subedit` function is also available as `sub`. It's a personal\npreference which you use. I like the way that `sub(edit, 'foo')` reads.\n\n## react-native support\n\nRequire it:\n\n```javascript\n  import {elegant, subedit} from 'elegant-react/native';\n```\n\nOr if you'd like to enable debug mode:\n\n```javascript\n  import ElegantReact from 'elegant-react/native';\n  const {elegant, subedit} = ElegantReact({debug: true});\n```\n\n## Using in codepen, jsbin, etc.\n\nAdd the script:\n\n    //rawgit.com/gilbox/elegant-react/master/build/global/elegant-react.js\n\nThis exposes the global object `ElegantReact`.\n\n```javascript\n  const {elegant, subedit} = ElegantReact;\n```\n\nOr if you'd like to enable `debug` mode:\n\n```javascript\n  const {elegant, subedit} = ElegantReact({debug: true});\n```\n\n## Usage\n\nFirst, make sure you understand the `subedit` (aka `sub`) function described in\n[this Medium article](https://medium.com/@gilbox/an-elegant-functional-architecture-for-react-faa3fb42b75b)\n\nThen add the `@elegant` decorator to your component, specifying which\nprops are static.\n\n```javascript\n  const inc = n =\u003e n + 1;\n\n  @elegant({statics: ['editValue']})\n  class Item extends Component {\n    render() {\n      const {item,editValue} = this.props;\n      const onClick = _ =\u003e editValue(inc);\n      return \u003cli onClick={ onClick }\u003e\n        { item.get('name') } - { item.get('value') }\n      \u003c/li\u003e\n    }\n  }\n```\n\nNow put that component to use:\n\n```javascript\n  const reverse = data =\u003e data.reverse();\n  @elegant({statics: ['edit']})\n  class Items extends Component {\n    render() {\n      const {items,edit} = this.props;\n\n      const children = items.toArray().map(\n        (item, index) =\u003e\n          \u003cItem key={item.get('name')}\n                item={item}\n                editValue={sub(edit, index,'value')} /\u003e );\n\n      return  \u003cdiv key=\"root\"\u003e\n        \u003cbutton onClick={_ =\u003e edit(reverse)}\u003ereverse\u003c/button\u003e\n        \u003cul\u003e{ children }\u003c/ul\u003e\n      \u003c/div\u003e;\n    }\n  }\n```\n\nThe rest of the source for this demo is [here](https://github.com/gilbox/elegant-react/blob/master/examples/reorder-items/app.js)\nand you can [see it in action](http://gilbox.github.io/elegant-react/examples/reorder-items/demo.html)\nas well.\n\n\n## dependencies\n\nYou might notice that elegant-react has no `dependencies` nor `peerDependencies`\nlisted in it's package.json file. This is so it can support both react and react-native\nfrom the same npm package.\n\nAlthough it's not a hard dependency, the provided `subedit` function is known\nto work with `immutable-js`. If you wish to use a different immutable lib,\njust create your own subedit function and it should work.\n\n- `sub`edit for [mori](http://swannodette.github.io/mori/) *(untested)*\n  ```javascript\n    const sub = (edit, ...path) =\u003e transform =\u003e\n      edit(state =\u003e mori.updateIn(state, path, transform));\n  ```\n\n- `sub`edit for [updeep](https://github.com/aaronjensen/updeep). \n  (There is a demo in the `examples/reorder-items-updeep/` dir.)\n  ```javascript\n    import u from 'updeep'\n    \n    const sub = (edit, ...path) =\u003e \n      transform =\u003e edit(u.updateIn(path, transform));\n  ```\n\n- `sub`edit for [icepick](https://github.com/aearly/icepick) *(untested)*\n  ```javascript\n    import i from 'icepick'\n    \n    const sub = (edit, ...path) =\u003e transform =\u003e \n      edit(state =\u003e i.updateIn(state, path, transform))\n  ```\n\n## Run the examples\n\nClone this repo, then:\n\n```bash\n  npm install\n  npm run examples\n```\n\n... and navigate to [http://localhost:8080/webpack-dev-server/](http://localhost:8080/webpack-dev-server/)\n\n\n## differences from omniscient\n\n- elegant-react uses higher-order components where omniscient uses mixins\n- elegant-react components use a decorator to specify which props are static while\n  omniscient uses a single prop called `statics`.\n- omniscient will perform deep comparisons on props of any type with `lodash.isequal`,\n  elegant-react only performs shallow comparison assuming that if you need deep comparison\n  you will use immutable objects or define your own `shouldComponentUpdate`\n- elegant-react uses idiomatic react approach ([see this article](https://medium.com/p/7acf5d0cf00e) for more info)\n- omniscient supports components as function without JSX\n- omniscient supports cursors\n- omniscient is battle-tested\n- omniscient is unit-tested\n- omniscient is ~18kb minified. elegant-react is ~4kb\n\n## live examples\n\n- [Phone Input](http://gilbox.github.io/elegant-react/examples/phone-input-field/demo.html)\n  A very simple example of how to use `elegant-react` and a functional approach to creating\n  an input component with custom formatting and masking rules.\n- [Address Book with Stream-based Plugins](http://gilbox.github.io/elegant-react/examples/address-book-store-streams/demo.html)\n  Demonstrates how to use streams to create an undo/redo plugin.\n  Introduces the concepts of `previousEditStream`, `editStream`, and `wiredStream` that allows a plugin to gain read and/or write\n  access only to specific parts of the application state.\n- [Scroll Spring Animation](http://gilbox.github.io/elegant-react/examples/scroll-spring-animation/demo.html)\n  Demonstrates how to use `react-springs` (or `react-animation`) and how to create a scroll\n  handling component using the same functional technique.\n- [Reorder Items](http://gilbox.github.io/elegant-react/examples/reorder-items/demo.html)\n  A very simple demo showing how to use `elegant-react`.\n- [Form Validation (wip)](http://gilbox.github.io/elegant-react/examples/form-validation/demo.html)\n  Demonstrates how to create a robust plugin to handle validating form fields with a\n  json scema using the `jjv` npm package. Also demonstrates how to compose\n  decorators by combining `@elegant` with `@validationDecorator`.\n- [Sticky](http://gilbox.github.io/elegant-react/examples/sticky/demo.html)\n  Make a `div` stick when the user scrolls the item past the top of the viewport.\n\n- **[elegant-react-hot-demo](https://github.com/gilbox/elegant-react-hot-demo)** - This github repo demonstrates stream-based plugins (with flyd), animation with react-motion, hot reload, and time-travel scrubbing.\n\n## credit\n\nThis project was originally a simplified version of [omniscient](http://omniscientjs.github.io/)\nwhich promotes the functional approach of [browser.html](https://github.com/mozilla/browser.html/).\nHowever, it has since evolved to become a more unique thing of it's own (see *differences from omniscient* above)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgilbox%2Felegant-react","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgilbox%2Felegant-react","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgilbox%2Felegant-react/lists"}