{"id":29275245,"url":"https://github.com/shoptap/redux-actioner","last_synced_at":"2026-05-03T12:39:22.566Z","repository":{"id":57350136,"uuid":"90434737","full_name":"Shoptap/redux-actioner","owner":"Shoptap","description":"Make Redux actions simple, predictable, and maintainable.","archived":false,"fork":false,"pushed_at":"2018-02-16T04:32:14.000Z","size":210,"stargazers_count":2,"open_issues_count":1,"forks_count":1,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-07-04T23:41:22.855Z","etag":null,"topics":["actions","redux","redux-observable","redux-saga"],"latest_commit_sha":null,"homepage":"https://shoptap.github.io/redux-actioner","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Shoptap.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":"2017-05-06T03:30:33.000Z","updated_at":"2019-10-08T18:45:39.000Z","dependencies_parsed_at":"2022-09-16T10:10:36.619Z","dependency_job_id":null,"html_url":"https://github.com/Shoptap/redux-actioner","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/Shoptap/redux-actioner","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Shoptap%2Fredux-actioner","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Shoptap%2Fredux-actioner/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Shoptap%2Fredux-actioner/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Shoptap%2Fredux-actioner/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Shoptap","download_url":"https://codeload.github.com/Shoptap/redux-actioner/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Shoptap%2Fredux-actioner/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":263692913,"owners_count":23496944,"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":["actions","redux","redux-observable","redux-saga"],"created_at":"2025-07-05T06:07:36.335Z","updated_at":"2026-05-03T12:39:22.521Z","avatar_url":"https://github.com/Shoptap.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Redux Actioner\nMake Redux actions simple, predictable, and maintainable.\n\n# Introduction\nCreating actions should be easy and consistent. Inspired by Flux Standard Actions, this framework facilitates the implementation of Redux actions for the sake of simplicity, testing, and maintainability.\n\n# Installation\n```\nyarn add redux-actioner\n```\n\n## Simplicity\nManage your actions like reducers. Redux Actioner provides `createActionFactory` which you can use to namespace your actions and add **Action Slices** that are broken down into three types: `REQUEST`, `SUCCESS`, and `FAILURE`.\n\n```javascript\n{\n  type: 'TODO/ADD/REQUEST',\n  baseType: 'TODO/ADD',\n  payload: {\n    text: 'Do something great.'\n  },\n  actionType: 'REQUEST'\n}\n```\nHere is our `REQUEST` action that is namespaced in the `TODO` factory \u003e `ADD` slice. The `baseType` property contains the factory namespace and the slice name for the ease of handling in reducers.\n\n## Maintainability\nRedux Actioner abstracts the frustration from creating objects and maintaining an application. Request action creators are reusable and easy to update when your API changes. Components remain pure of API versioning and integration with [Redux Saga](https://github.com/redux-saga/redux-saga) and [Redux Observable](https://github.com/redux-observable/redux-observable) is seamless.\n\n## Usage\n### Define Actions\n```javascript\nimport { createActionFactory, request } from 'redux-actioner';\nconst createSliceAction = createActionFactory('TODO');\n\nexport const ADD = createSliceAction('ADD', ({ text, title, listId: list_id })\n  =\u003e ({ text, title, list_id }));\n\n/*\nADD = {\n  baseType: 'TODO/ADD',\n  REQUEST: 'TODO/ADD/REQUEST',\n  SUCCESS: 'TODO/ADD/SUCCESS',\n  FAILURE: 'TODO/ADD/FAILURE',\n  requestPayloadCreator: ({ text, title, listId: list_id })\n    =\u003e ({ text, title, list_id }))\n}\n*/\n```\nIn the example above we have created a namespace called \"TODO\" and added an action to it called \"ADD.\" In the comment we can see the `baseType` is `TODO/ADD` which will make it easy to bind and reduce. The payload creator is included for creating request action types which makes for a predictable payload.\n\n\n### Bind to Dispatch\n```javascript\nimport { connect } from 'react-redux';\nimport { bindRequestActions } from 'redux-actioner';\nimport * as TodoActions from '../actions';\n\nclass TodoForm extends React.Component {\n  state = { text: \"Do something greatest.\", title: \"Tomorrow...\" }\n\n  onSubmit() {\n    this.props.actions.addTodoItem({\n      listId: this.props.listID,\n      ...this.state.form\n    });\n  }\n\n  render() {\n    \u003cForm onSubmit={() =\u003e this.onSubmit()} /\u003e\n  }\n}\n\nconst mapDispatchToProps = (dispatch) =\u003e {\n  return {\n    actions: bindRequestActions({\n      addTodoItem: TodoActions.ADD\n    }, dispatch);\n  };\n}\n\nexport default connect(mapStateToProps, mapDispatchToProps)(TodoForm);\n```\n\nThe example above will feel familiar with the only difference being that Actioner does not require action creators in your components. ActionSlice objects are given to `bindRequestActions` which will return an object of action creators similar to Redux's `bindActionCreators`. This keeps components clean of API changes and minimizes redundancies.\n\n### Reduce and Slice\n\n```javascript\nimport * as TodoActions from '../actions';\n\nfunction todoReducer(state = { items: [], isSubmitting: null }, action) {\n  const { baseType } = action;\n\n  switch(baseType) {\n    case TodoActions.ADD.BASE_TYPE:\n      return addSlice(state, action);\n    case TodoActions.REMOVE.BASE_TYPE:\n      return removeSlice(state, action);\n  }\n}\n\nfunction addSlice(state, action) {\n  const { actionType, payload } = action;\n  switch (actionType ) {\n    case 'REQUEST':\n      return { ...state, isSubmitting: true };\n    case 'SUCCESS':\n      const newTodo = { createdAt: new Date(), ...payload };\n      return { isSubmitting: false, items: state.items.concat(newTodo) };\n    break;\n  }\n}\n```\n\nIn the example above you will see our `todoReducer` which has been abstracted into slices to deal with ActionSlice types. When working with large reducers and many actions it becomes a necessity to break out into slices. The end result is cleaner and easier to manage.\n\n### Action Context\nWhen managing side effects it can be difficult to keep track of data as it flows from action to action. Maintaining context is important to ensure actions that respond to requests can resolve later on when reducing.\n\nPayload data from a request action can be abstracted and dispatched in success or failure actions by providing `context` to `success(actionSlice, context)` or `failure(actionSlice, context)`:\n\n```javascript\nconst requestAction = request(TodoActions.ADD)({ text: \"Do something most great.\"});\nconst { payload } = requestAction;\nconst { text } = payload;\nfetch(apiRequest)\n  .then(response =\u003e\n    const successAction = success(TodoActions.ADD, { text })(response);\n    store.dispatch(successAction);\n  )\n  .catch(error =\u003e\n    const errorAction = failure(TodoActions.ADD, { text })(error);\n    store.dispatch(errorAction);\n  );\n```\n\n## Testing\nBy using standardized payload creators, action data becomes more predictable and easier to test.\n\nThe payload to a `REQUEST` action is reduced through a function to prepare the `payload` parameters for dispatch. It makes API changes flexible and easy to manage in action creators.\n\n\n```javascript\ndescribe(\"TODO/ADD request action\", () =\u003e {\n  const payload = { text: 'Do something greater.', title: 'Today...', listId: 1 };\n\n  it(\"converts from camel case to snake case\", () =\u003e {\n    expect(request(TodoActions.ADD)(payload))\n      .toEqual(jasmine.objectContaining({\n        text: payload.text,\n        title: payload.title,\n        list_id: payload.listId\n      }));\n  }\n})\n```\n\n# Manual\n\n- [API Reference](https://Shoptap.github.io/redux-actioner)\n- [Integration with Redux Saga](/manual/saga.md)\n- [Integration with Redux Observable](/manual/observable.md)\n\n# Contributors\n- [Peter Salanki](https://github.com/salanki)\n- [Cole Turner](https://github.com/colepatrickturner)\n- [Poyan Nabati](https://github.com/nabati)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fshoptap%2Fredux-actioner","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fshoptap%2Fredux-actioner","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fshoptap%2Fredux-actioner/lists"}