{"id":17823765,"url":"https://github.com/andersdjohnson/redux-reducer-async","last_synced_at":"2025-07-06T01:33:35.380Z","repository":{"id":22366088,"uuid":"96043376","full_name":"AndersDJohnson/redux-reducer-async","owner":"AndersDJohnson","description":"Create redux reducers for async behaviors of multiple actions.","archived":false,"fork":false,"pushed_at":"2023-01-12T09:52:42.000Z","size":813,"stargazers_count":14,"open_issues_count":18,"forks_count":2,"subscribers_count":2,"default_branch":"master","last_synced_at":"2024-04-14T05:16:05.247Z","etag":null,"topics":["action","actions","async","flux","flux-architecture","flux-pattern","flux-standard-action","fsa","fsa-actions","promise","promises","react","reducer","reducer-creation","reducers","redux"],"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/AndersDJohnson.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null},"funding":{"github":"AndersDJohnson"}},"created_at":"2017-07-02T19:05:09.000Z","updated_at":"2023-11-07T12:45:58.000Z","dependencies_parsed_at":"2023-01-13T21:58:50.204Z","dependency_job_id":null,"html_url":"https://github.com/AndersDJohnson/redux-reducer-async","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/AndersDJohnson%2Fredux-reducer-async","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AndersDJohnson%2Fredux-reducer-async/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AndersDJohnson%2Fredux-reducer-async/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AndersDJohnson%2Fredux-reducer-async/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/AndersDJohnson","download_url":"https://codeload.github.com/AndersDJohnson/redux-reducer-async/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243945539,"owners_count":20372896,"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":["action","actions","async","flux","flux-architecture","flux-pattern","flux-standard-action","fsa","fsa-actions","promise","promises","react","reducer","reducer-creation","reducers","redux"],"created_at":"2024-10-27T17:59:26.059Z","updated_at":"2025-03-18T16:30:43.328Z","avatar_url":"https://github.com/AndersDJohnson.png","language":"JavaScript","funding_links":["https://github.com/sponsors/AndersDJohnson"],"categories":[],"sub_categories":[],"readme":"# redux-reducer-async\n\u003e Create redux reducers for async behaviors of multiple actions.\n\n[![npm](https://img.shields.io/npm/v/redux-reducer-async.svg)](https://npmjs.com/package/redux-reducer-async)\n[![Travis CI](https://img.shields.io/travis/AndersDJohnson/redux-reducer-async.svg)](https://travis-ci.org/AndersDJohnson/redux-reducer-async)\n[![Codecov](https://img.shields.io/codecov/c/github/AndersDJohnson/redux-reducer-async.svg)](https://codecov.io/gh/AndersDJohnson/redux-reducer-async)\n\nBe DRY \u0026 reduce boilerplate.\nStandardize state schema with managed properties for loading, success, and error cases.\n\nThink of it as [`redux-actions`](https://redux-actions.js.org/) for asynchronous reducers.\n\nWorks with [Flux Standard Actions (FSA)][FSA].\nBy default, supports the action type conventions of [`redux-promise-middleware`][redux-promise-middleware],\nbut see [Custom Action Types](#custom-action-types) below for configuration to support [`redux-promise`][redux-promise].\n\n## Install\n\n[![npm install --save redux-reducer-async (copy)](https://copyhaste.com/i?t=npm%20install%20--save%20redux-reducer-async)](https://copyhaste.com/c?t=npm%20install%20--save%20redux-reducer-async \"npm install --save redux-reducer-async (copy)\")\n\n## Use\n\n```js\nimport createReducer from 'redux-reducer-async'\n\nconst myActionReducer = createReducer('MY_ACTION')\n```\n\nresults in a reducer like this:\n\n```js\n(state = {}, action = {}) =\u003e {\n  switch (action.type) {\n    case 'MY_ACTION_PENDING':\n      return { ...state, loading: true, error: null }\n    case 'MY_ACTION_FULFILLED':\n      return { ...state, loading: false, error: null, data: action.payload }\n    case 'MY_ACTION_REJECTED':\n      return { ...state, loading: false, error: action.payload }\n    default:\n      return state\n  }\n}\n```\n\nYou can then mount it with [`combineReducers`](http://redux.js.org/docs/api/combineReducers.html):\n\n```js\nimport { combineReducers } from 'redux'\nimport createReducer from 'redux-reducer-async'\n\nconst rootReducer = combineReducers({\n  myAction: createReducer('MY_ACTION')\n})\n```\n\nOr even call it manually within another reducer (useful with [custom properties](#custom-properties) or [reducers](#custom-reducers)):\n\n```js\nimport createReducer from 'redux-reducer-async'\n\nconst myActionReducer = createReducer('MY_ACTION')\n\nconst reducer = (state = {}, action = {}) =\u003e {\n  state = myActionReducer(state, action)\n  // ...\n  return state\n}\n```\n\n### Custom Properties\n\nYou can provide custom property names (all optional) for each case to be used on the state:\n\n```js\ncreateReducer('MY_ACTION', {\n  loading: 'isMyActionLoading',\n  success: 'myActionData',\n  error: 'myActionError'\n})\n```\n\n### Custom Reducers\n\nYou can also provide custom reducer functions (again all optional, but be careful to define all cases if you use non-standard property names in one):\n\n\u003c!-- global createReducer --\u003e\n```js\ncreateReducer('MY_ACTION', {\n  loading: state =\u003e ({\n    ...state,\n    myActionError: null,\n    myActionIsLoading: true,\n    extra: 'whatever'\n  })\n  // success, error...\n})\n```\n\nAnd you can even mix these with custom properties:\n\n\u003c!-- global createReducer --\u003e\n```js\ncreateReducer('MY_ACTION', {\n  loading: 'isLoading',\n  error: (state, action) =\u003e ({\n    ...state,\n    isLoading: false,\n    error: action.payload,\n    also: 'etc'\n  })\n})\n```\n\n### Custom Action Types\n\nYou can provide custom action types.\n\nFor example, to support [`redux-promise`][redux-promise], which uses same the action type for success and error cases (though it does not provide a loading action),\nyou can use `finalActionType`:\n\n```js\nimport createReducer, { finalActionType } from 'redux-reducer-async'\n\ncreateReducer(finalActionType('MY_ACTION'))\n```\n\nwhich is effectively like providing custom action types:\n\n```js\ncreateReducer({\n  loading: 'MY_ACTION_PENDING',\n  success: 'MY_ACTION',\n  error: 'MY_ACTION'\n})\n```\n\nOr similarly by passing suffixes to the `actionTypes` helper,\nwhich is normally used to explicitly define all types:\n\n```js\nimport createReducer, { actionTypes } from 'redux-reducer-async'\n\ncreateReducer(actionTypes('MY_ACTION', '_LOADING', '_SUCCESS', '_ERROR'))\n```\n\nBut can also be used to suppress suffixes (here undefined means use default):\n\n```js\ncreateReducer(actionTypes('MY_ACTION', undefined, '', ''))\n```\n\n### Transforms\n\nAs a shortcut to defining custom reducers, you can provide transform functions to manipulate only the payload, optionally in success and/or error cases:\n\n```js\ncreateReducer('MY_ACTION', {\n  transform: payload =\u003e ({\n    ...payload,\n    title: payload.title.trim()\n  }),\n  transformError: payload =\u003e ({\n    ...payload,\n    message: `There was an error: ${payload.message}`\n  })\n})\n```\n\n[redux-promise-middleware]: https://github.com/pburtchaell/redux-promise-middleware\n[redux-promise]: https://github.com/acdlite/redux-promise\n[FSA]: https://github.com/acdlite/flux-standard-action\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fandersdjohnson%2Fredux-reducer-async","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fandersdjohnson%2Fredux-reducer-async","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fandersdjohnson%2Fredux-reducer-async/lists"}