{"id":26761698,"url":"https://github.com/richardcrng/riduce","last_synced_at":"2025-04-15T09:11:56.300Z","repository":{"id":46817091,"uuid":"291568301","full_name":"richardcrng/riduce","owner":"richardcrng","description":"Get rid of your reducer boilerplate! Zero hassle state management that's typed, flexible and scalable.","archived":false,"fork":false,"pushed_at":"2023-01-08T16:06:26.000Z","size":17029,"stargazers_count":15,"open_issues_count":0,"forks_count":0,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-04-15T09:11:46.890Z","etag":null,"topics":["javascript","reducer","reducer-creation","reducers","redux","state","state-management","typescript","use-reducer","usereducer"],"latest_commit_sha":null,"homepage":"https://richardng.notion.site/Riduce-3cb629505a8d49279fe8848e1d564deb","language":"TypeScript","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/richardcrng.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}},"created_at":"2020-08-30T23:18:48.000Z","updated_at":"2023-08-07T21:36:48.000Z","dependencies_parsed_at":"2023-02-08T06:31:42.310Z","dependency_job_id":null,"html_url":"https://github.com/richardcrng/riduce","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/richardcrng%2Friduce","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/richardcrng%2Friduce/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/richardcrng%2Friduce/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/richardcrng%2Friduce/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/richardcrng","download_url":"https://codeload.github.com/richardcrng/riduce/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":249040110,"owners_count":21202820,"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":["javascript","reducer","reducer-creation","reducers","redux","state","state-management","typescript","use-reducer","usereducer"],"created_at":"2025-03-28T18:26:46.095Z","updated_at":"2025-04-15T09:11:56.281Z","avatar_url":"https://github.com/richardcrng.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Riduce 👻\n\n**Get *rid* of your reducer boilerplate!**\n\n*Zero hassle state management that's typed, flexible and scalable.*\n\n```bash\nnpm install riduce\n```\n\n![Travis (.org)](https://img.shields.io/travis/richardcrng/riduce.svg)\n[![bundle size](https://badgen.net/bundlephobia/min/riduce)](https://badgen.net/bundlephobia/min/riduce)\n[![npm version](https://badge.fury.io/js/riduce.svg)](https://badge.fury.io/js/riduce)\n\n[![Edit Riduce example - MadLibs for Developers](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/riduce-example-madlibs-for-developers-njo9t?fontsize=14\u0026hidenavigation=1\u0026theme=dark\u0026view=preview)\n\nWhether you're using `useReducer` or `redux`, reducer boilerplate is tedious to learn, setup and maintain.\n\nWhat if type-safe state management was quicker, easier and simpler?\n\nRiduce is a library written to be:\n- **Strongly-typed**, so your state stays predictable\n- **Trivial to scale** as your state grows more complex\n- **Zero hassle**, with *just two lines of code...*\n\n*... and one of the 2 lines to setup is an `import`.*\n\n```ts\nimport riduce from 'riduce'\n\nconst [reducer, actions] = riduce(initialState)\n```\n\nThat's it! Now you've got a type-safe `reducer` and arbitrary `actions`, with zero hassle.\n\nLet's see it in use!\n\n\u003e 🚧  Full documentation for Riduce is under construction - but the API is essentially the same as [Redux-Leaves](https://redux-leaves.js.org), except `riduce` replaces the `reduxLeaves` default export.\n\u003e Currently documented here are indicative examples on setup, usage and customisation. These give quite a lot of information about how the library is used.\n\u003e For more specifics, please consult the Redux-Leaves documentation to see, e.g., the [default action creators](https://redux-leaves.js.org/docs/defaults/overview) which [`create`](https://redux-leaves.js.org/docs/api/create) gives access to.\n\n# Introductory Example\nFor a `useReducer` example, [see this CodeSandbox](https://codesandbox.io/s/riduce-example-madlibs-for-developers-njo9t).\n\nFor a `redux` example, you can run this [Repl.it](https://repl.it/@richardcrng/Riduce-with-Redux).\n\nFor more advanced usage of Riduce, see [this example](./docs/riduce-advanced.md).\n\nBelow, we'll walk through the introductory Redux example, showing:\n1. [Zero hassle setup](#zero-hassle-setup) with 2 lines of code;\n2. [Scalable state management](#scalable-state-management) with arbitrary actions; and\n3. [Typesafe action creators](#typesafe-action-creators) to mirror your state's shape.\n\n## Zero hassle setup\nLet's imagine we're controlling the state for a museum.\n```ts\nimport { createStore } from 'redux'\nimport riduce from 'riduce' // 1st line: import\n\nconst museumState = {\n  isOpen: false,\n  visitor: {\n    counter: 0,\n    guestbook: ['richard woz here']\n  }\n}\n\nconst [reducer, actions] = riduce(museumState) // 2nd line: setup\nconst { getState, dispatch } = createStore(reducer)\n```\n**And that's it.** Those two lines replace *all* of our reducer boilerplate.\n\n## Scalable state management\nContinuing on from [above](#zero-hassle-setup), let's:\n1. Open our museum;\n2. Add to the visitor counter;\n3. Sign the guestbook; and\n4. Amend a guestbook entry.\n\nPreviously, you might create 4 x reducer branches, action types and action creators.\n\n**Riducer gets rid of all that boilerplate.**\n\nNow, it's as simple as describing the changes we want to see!\n\n```ts\n// at `state.isOpen`, create an action to toggle the boolean\ndispatch(actions.isOpen.create.toggle())\n\n// at `state.visitor.counter`, create an action to add 5\ndispatch(actions.visitor.counter.create.increment(5))\n\n// at `state.visitor.guestbook`, create an action to push a string\ndispatch(actions.visitor.guestbook.create.push('LOL from js fan'))\n\n// at `state.visitor.guestbook[0]`, create an action to concat a string\ndispatch(actions.visitor.guestbook[0].create.concat('!!!'))\n\ngetState()\n/*\n{\n  isOpen: true,\n  visitor: {\n    counter: 5,\n    guestbook: [\n      'richard woz here!!!',\n      'LOL from js fan'\n    ]\n  }\n}\n*/\n```\nAll this is possible because Riduce's `actions` gives you **loads of convenient action creators out of the box**, which you can *use liberally throughout your state tree:* `update`, `set`, `filter`, `reset`, and many more...\n\nIt's also possible to add your own in, as documented in [advanced Riduce usage](./docs/riduce-advanced.md).\n\n## Typesafe action creators\nNow we've seen that Riduce is [zero-hassle setup](#zero-hassle-setup) for [arbitrary action creators without the reducer boilerplate](#scalable-state-management). \n\nIt's written in TypeScript, so it's helpfully typed right out of the box as well!\n\n```ts\n// can we push to a boolean? no!\n// ❌ TypeError: (ts 2339) Property 'push' does not exist on type...\nactions.isOpen.create.push()\n\n// can we push to an array without an argument? no!\n// ❌ TypeError: (ts 2554) Expected 1-3 arguments, but got 0.\nactions.visitor.guestbook.create.push()\n\n// can we push a number to an inferred string[]? no!\n// ❌ TypeError: (ts 2345) Argument of type '10' is not assignable to parameter of type 'string'.\nactions.visitor.guestbook.create.push(10)\n\n// can we push a string to an inferred string[]? yeah, okay then.\n// ✅ compiles!\nactions.visitor.guestbook.create.push('10')\n```\n\n# Get started\nYou may wish to check out the following:\n- [Riduce: advanced usage](./docs/riduce-advanced.md)\n- [Riduce with `useReducer`: CodeSandbox demo](https://codesandbox.io/s/riduce-example-madlibs-for-developers-njo9t)\n- [Riduce with Redux: Repl.it demo](https://repl.it/@richardcrng/Riduce-with-Redux)\n\nAdvanced Riduce usage includes:\n1. [Bundle multiple actions](./docs/riduce-advanced.md#bundle-multiple-actions) into a single dispatch;\n2. [Execute arbitrary reducer logic](./docs/riduce-advanced.md#execute-arbitrary-reducer-logic) for extendability;\n3. [Add custom reducers](./docs/riduce-advanced.md#add-custom-reducers) for reusability; and\n4. [Control action types](./docs/riduce-advanced.md#control-action-types) for debugging (e.g. Redux DevTools).\n\nHave fun adding it to your project!\n\n```bash\nnpm install riduce\n```\n\n\u003e 🚧  Full documentation for Riduce is under construction - but the API is essentially the same as [Redux-Leaves](https://redux-leaves.js.org), except `riduce` replaces the `reduxLeaves` default export.\n\u003e Currently documented here are indicative examples on setup, usage and customisation. These give quite a lot of information about how the library is used.\n\u003e For more specifics, please consult the Redux-Leaves documentation to see, e.g., the [default action creators](https://redux-leaves.js.org/docs/defaults/overview) which [`create`](https://redux-leaves.js.org/docs/api/create) gives access to.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frichardcrng%2Friduce","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frichardcrng%2Friduce","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frichardcrng%2Friduce/lists"}