{"id":20495315,"url":"https://github.com/kevinast/astx-redux-util","last_synced_at":"2025-04-13T17:43:40.252Z","repository":{"id":57185393,"uuid":"79841913","full_name":"KevinAst/astx-redux-util","owner":"KevinAst","description":"Several redux reducer composition utilities.","archived":false,"fork":false,"pushed_at":"2017-04-11T17:37:54.000Z","size":1293,"stargazers_count":9,"open_issues_count":0,"forks_count":3,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-04-03T11:36:38.838Z","etag":null,"topics":["higher-order-reducers","reducer-composition","redux"],"latest_commit_sha":null,"homepage":"https://astx-redux-util.js.org/","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/KevinAst.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2017-01-23T19:55:09.000Z","updated_at":"2019-03-26T19:38:04.000Z","dependencies_parsed_at":"2022-09-14T10:02:59.482Z","dependency_job_id":null,"html_url":"https://github.com/KevinAst/astx-redux-util","commit_stats":null,"previous_names":[],"tags_count":6,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/KevinAst%2Fastx-redux-util","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/KevinAst%2Fastx-redux-util/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/KevinAst%2Fastx-redux-util/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/KevinAst%2Fastx-redux-util/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/KevinAst","download_url":"https://codeload.github.com/KevinAst/astx-redux-util/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248756493,"owners_count":21156779,"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":["higher-order-reducers","reducer-composition","redux"],"created_at":"2024-11-15T17:45:26.067Z","updated_at":"2025-04-13T17:43:40.226Z","avatar_url":"https://github.com/KevinAst.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# astx-redux-util\n\nThe [astx-redux-util] library promotes several redux reducer\ncomposition utilities, which blend multiple reducers together forming\na richer abstraction through functional decomposition\n(i.e. higher-order functions).\n\nReducer composition is not new.  Redux itself provides the innovative\n[combineReducers](http://redux.js.org/docs/api/combineReducers.html)\nutility which allows you to fuse individual reducers together to build\nup the overall shape of your application state.\n\nThe most prevalent [astx-redux-util] utility is **reducerHash()**,\nwhich lets you combine sub-reducers in such a way as to eliminate\nthe switch statement commonly used to delineate action type.  \n\n**Additionally**, [astx-redux-util] promotes other reducer compositions that\ncan be used in conjunction with one another.\n\n\u003c!--- Badges for CI Builds ---\u003e \n[![Build Status](https://travis-ci.org/KevinAst/astx-redux-util.svg?branch=master)](https://travis-ci.org/KevinAst/astx-redux-util)\n[![Codacy Badge](https://api.codacy.com/project/badge/Grade/b7e9e537a56e41a692aef023fd15d9ca)](https://www.codacy.com/app/KevinAst/astx-redux-util?utm_source=github.com\u0026amp;utm_medium=referral\u0026amp;utm_content=KevinAst/astx-redux-util\u0026amp;utm_campaign=Badge_Grade)\n[![Codacy Badge](https://api.codacy.com/project/badge/Coverage/b7e9e537a56e41a692aef023fd15d9ca)](https://www.codacy.com/app/KevinAst/astx-redux-util?utm_source=github.com\u0026amp;utm_medium=referral\u0026amp;utm_content=KevinAst/astx-redux-util\u0026amp;utm_campaign=Badge_Coverage)\n[![Known Vulnerabilities](https://snyk.io/test/github/kevinast/astx-redux-util/badge.svg)](https://snyk.io/test/github/kevinast/astx-redux-util)\n[![NPM Version Badge](https://img.shields.io/npm/v/astx-redux-util.svg)](https://www.npmjs.com/package/astx-redux-util)\n\n## Comprehensive Documentation\n\nComplete documentation can be found at\nhttps://astx-redux-util.js.org/, which includes both **API** details,\nand a **Dev Guide** with full and thorough **examples**!\n\n\n## Install\n\n```shell\nnpm install --save astx-redux-util\n```\n\n\n## Examples\n\n### Basics\n\nThe following example uses **reducerHash()** to combine a set of\nsub-reducer functions (indexed by the standard action.type),\neliminating the switch statement commonly used to delineate action\ntype.\n\n**Don't miss the [astx-redux-util] documentation**, *which fully explores\nthis example, and details the API.*\n\n```js\nimport { reducerHash } from 'astx-redux-util';\n\nexport default reducerHash({\n  \"widget.edit\":       (widget, action) =\u003e action.widget,\n  \"widget.edit.close\": (widget, action) =\u003e null,\n}, null);\n```\n\n\n### Joining Reducers\n\nBuilding on the previous example, our widget now takes on more detail:\n - we manage x/y properties (through the standard\n   [combineReducers](http://redux.js.org/docs/api/combineReducers.html))\n - the widget itself can take on a null value (an indication it is NOT\n   being edited)\n\nWe manage these new requirements by combining multiple reducers\nthrough a functional decomposition (as opposed to procedural code).\nTo accomplish this, we add to our repertoire by introducing\n**joinReducers()** and **conditionalReducer()**.\n\n**Did I mention that the [astx-redux-util] documentation**, *fully explores\nthis example, and details the API?*\n\n```js\nimport * as Redux         from 'redux';\nimport * as AstxReduxUtil from 'astx-redux-util';\nimport x                  from '../appReducer/x';\nimport y                  from '../appReducer/y';\n\nexport default AstxReduxUtil.joinReducers(\n  // FIRST: determine content shape (i.e. {} or null)\n  AstxReduxUtil.reducerHash({\n    \"widget.edit\":       (widget, action) =\u003e action.widget,\n    \"widget.edit.close\": (widget, action) =\u003e null\n  }),\n\n  AstxReduxUtil.conditionalReducer(\n    // SECOND: maintain individual x/y fields\n    //         ONLY when widget has content (i.e. is being edited)\n    (widget, action, originalReducerState) =\u003e widget !== null,\n    Redux.combineReducers({\n      x,\n      y\n    })),\n\n  null); // initialState\n```\n\n### Full Example\n\nBuilding even more on the prior examples:\n - our widget adds a curHash property (which is a determinate of\n   whether application content has changed)\n\nWe manage this new property in the parent widget reducer, because it\nhas a unique vantage point of knowing when the widget has changed\n(under any circumstance, regardless of how many properties are\ninvolved).\n\nWe accomplish this by simply combining yet another reducer (using a\nfunctional approach).  This also demonstrates how **composition can be\nnested!**\n\n**Read all about it!  The [astx-redux-util] documentation** *fully explores\nthis example, and details the API.*\n\n```js\nimport * as Redux         from 'redux';\nimport * as AstxReduxUtil from 'astx-redux-util';\nimport x                  from '../appReducer/x';\nimport y                  from '../appReducer/y';\nimport Widget             from '../appReducer/Widget';\n\nexport default AstxReduxUtil.joinReducers(\n  // FIRST: determine content shape (i.e. {} or null)\n  AstxReduxUtil.reducerHash({\n    \"widget.edit\":       (widget, action) =\u003e action.widget,\n    \"widget.edit.close\": (widget, action) =\u003e null\n  }),\n\n  AstxReduxUtil.conditionalReducer(\n    // NEXT: maintain individual x/y fields\n    //       ONLY when widget has content (i.e. is being edited)\n    (widget, action, originalReducerState) =\u003e widget !== null,\n    AstxReduxUtil.joinReducers(\n      Redux.combineReducers({\n        x,\n        y,\n        curHash: (s=null)=\u003es // defaulted state placebo reducer (needed by combineReducers())\n      }),\n      AstxReduxUtil.conditionalReducer(\n        // LAST: maintain curHash\n        //       ONLY when widget has content (see condition above) -AND- has changed\n        (widget, action, originalReducerState) =\u003e originalReducerState !== widget,\n        (widget, action) =\u003e {\n          widget.curHash = Widget.hash(widget); // OK to mutate (because of changed instance)\n          return widget;\n        })\n    )\n  ), null); // initialState\n```\n\nThis represents a very comprehensive example of how **Reducer\nComposition** can **simplify your life**!  We have combined multiple\nreducers into one, applying conditional logic as needed through\nfunctional decomposition!\n\n\n[astx-redux-util]: https://astx-redux-util.js.org/\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkevinast%2Fastx-redux-util","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkevinast%2Fastx-redux-util","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkevinast%2Fastx-redux-util/lists"}