{"id":17658690,"url":"https://github.com/xcarpentier/react-redux-dispatch-async","last_synced_at":"2025-09-07T04:34:56.660Z","repository":{"id":42800547,"uuid":"210387608","full_name":"xcarpentier/react-redux-dispatch-async","owner":"xcarpentier","description":"🎸 react-redux hook \u0026 redux middleware to be able to wait for async actions with fixed defined suffixes","archived":false,"fork":false,"pushed_at":"2023-01-07T19:02:26.000Z","size":1091,"stargazers_count":7,"open_issues_count":14,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-05-07T12:48:27.646Z","etag":null,"topics":["async","async-actions","react","react-hooks","redux"],"latest_commit_sha":null,"homepage":"https://codesandbox.io/s/react-redux-dispatch-async-rij31","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/xcarpentier.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null},"funding":{"github":"xcarpentier","patreon":null,"open_collective":null,"ko_fi":null,"tidelift":null,"community_bridge":null,"liberapay":null,"issuehunt":null,"otechie":null,"custom":null}},"created_at":"2019-09-23T15:18:21.000Z","updated_at":"2021-04-01T07:29:45.000Z","dependencies_parsed_at":"2023-02-07T22:00:58.062Z","dependency_job_id":null,"html_url":"https://github.com/xcarpentier/react-redux-dispatch-async","commit_stats":null,"previous_names":[],"tags_count":4,"template":false,"template_full_name":null,"purl":"pkg:github/xcarpentier/react-redux-dispatch-async","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xcarpentier%2Freact-redux-dispatch-async","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xcarpentier%2Freact-redux-dispatch-async/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xcarpentier%2Freact-redux-dispatch-async/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xcarpentier%2Freact-redux-dispatch-async/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/xcarpentier","download_url":"https://codeload.github.com/xcarpentier/react-redux-dispatch-async/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xcarpentier%2Freact-redux-dispatch-async/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":262863710,"owners_count":23376453,"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":["async","async-actions","react","react-hooks","redux"],"created_at":"2024-10-23T15:28:27.279Z","updated_at":"2025-06-30T23:03:52.686Z","avatar_url":"https://github.com/xcarpentier.png","language":"TypeScript","funding_links":["https://github.com/sponsors/xcarpentier"],"categories":[],"sub_categories":[],"readme":"\u003cp\u003e\n  \u003ca href=\"https://www.npmjs.com/package/react-redux-dispatch-async\"\u003e\n  \u003cimg alt=\"npm version\" src=\"https://badge.fury.io/js/react-redux-dispatch-async.svg\"/\u003e\u003c/a\u003e\n    \u003ca href=\"https://www.npmjs.com/package/react-redux-dispatch-async\"\u003e\u003cimg alt=\"npm downloads\" src=\"https://img.shields.io/npm/dm/react-redux-dispatch-async.svg\"/\u003e\u003c/a\u003e\n  \u003ca href=\"#hire-an-expert\"\u003e\n      \u003cimg src=\"https://img.shields.io/badge/%F0%9F%92%AA-hire%20an%20expert-brightgreen\"/\u003e\n    \u003c/a\u003e\n\u003cp\u003e\n\n# react-redux-dispatch-async\n\n👉 REDUX _middleware_ \u0026 **HOOK** 🎉 waiting async _actions_ with **SUFFIXES** 👈\n\n```tsx\nimport { useDispatchAsync } from 'react-redux-dispatch-async'\n\nexport default function MyUserInterface({ id }: { id: string }) {\n  // 👉 pass action and arguments into the array\n  const response = useDispatchAsync(getUserActionRequest, [id])\n\n  switch (response.status) {\n    case 'loading':\n      return \u003cAppLoader /\u003e\n    case 'error':\n      return \u003cText\u003e{response.error.message}\u003c/Text\u003e\n    case 'success':\n      return \u003cUser {...response.result} /\u003e\n    case 'timeout':\n      return \u003cText\u003e{'timeout ¯\\\\_(ツ)_//¯'}\u003c/Text\u003e\n    case 'canceled':\n      return \u003cText\u003e{'canceled ¯\\\\_(ツ)_//¯'}\u003c/Text\u003e\n    default:\n      return null\n  }\n}\n```\n\nIf you need more examples you can go to [github](https://github.com/xcarpentier/react-redux-dispatch-async-example) or to [codesandbox](https://codesandbox.io/s/react-redux-dispatch-async-rij31?file=/src/UserContainer.tsx).\n\n## Install\n\n`yarn add react-redux-dispatch-async`\n\n## Features\n```\n\n      +------------------+\n      | ACTION_REQUESTED |----+\n      +------------------+    |      +------------------+\n                              +-----\u003e| ACTION_SUCCEEDED |\n                              |      +------------------+\n                              |\n                              |      +--------------------+\n                              +-----\u003e|   ACTION_FAILED    |\n                              |      +--------------------+\n                              |\n                              |      +--------------------+\n                              +-----\u003e|  ACTION_CANCELED  |\n                                     +--------------------+\n```\n\n### Race condition to execute only the promise if multiple update occur in nearly same time\n\n[\u003e Dig into it](https://github.com/xcarpentier/react-redux-dispatch-async/blob/master/src/useDispatchAsync.ts#L65)\n\n### Hook give you helpful STATUS you can deal with into your own component\n\n- ⏳ **`loading`**: action start but not yet completed\n- 👏 **`success`**: action completed, you can get the result\n- 😱 **`error`**: action failed and you can get the error\n- 👎 **`timeout`**: action not completed for too long (ie. options?.timeoutInMilliseconds)\n- 👋 **`canceled`**: action canceled\n- 😮 **`unknown`**: should never happen\n\n### Configuration\n\n```ts\nimport { createStore, applyMiddleware } from 'redux'\nimport { createDispatchAsyncMiddleware } from 'react-redux-dispatch-async'\nimport reducers from 'reducers'\n\nconst store = createStore(\n  reducers,\n  applyMiddleware(\n    createDispatchAsyncMiddleware({\n      request: 'REQUEST', // 👈 define your own async suffixes\n      success: 'SUCCESS',\n      failure: 'FAILURE',\n      cancel: 'CANCEL', // optional\n    }),\n  ),\n)\n```\n\n## Default suffixes\n\n- `[...]_REQUESTED`\n- `[...]_SUCCEEDED`\n- `[...]_FAILED`\n- `[...]_CANCELED`\n\n## Two functions\n\n### Configuration\n\n```ts\ndispatchAsyncMiddleware: (c?: {\n  request: string\n  success: string\n  failure: string\n  cancel?: string\n}) =\u003e redux.Middleware\n```\n\n### Type\n\n```ts\n// main hook\ninterface Options {\n  timeoutInMilliseconds?: number\n}\ntype useDispatchAsync = \u003cR = any\u003e(\n  actionFunction?: (...args: any[]) =\u003e Action\u003cT\u003e,\n  deps: any[] = [],\n  options: Options = { timeoutInMilliseconds: 15000 }, // wait 15s\n) =\u003e UseDispatchAsync\u003cR\u003e\n\n/// return type\ninterface ResultLoading {\n  status: 'loading'\n}\n\ninterface ResultSuccess\u003cR = unknown\u003e {\n  status: 'success'\n  result: R\n}\n\ninterface ResultError {\n  status: 'error'\n  error: Error\n}\n\ninterface ResultCancel {\n  status: 'canceled'\n}\n\ninterface ResultTimeout {\n  status: 'timeout'\n}\n\ninterface ResultUnknown {\n  status: 'unknown'\n}\n\nexport type UseDispatchAsync\u003cR = unknown\u003e =\n  | ResultLoading\n  | ResultSuccess\u003cR\u003e\n  | ResultError\n  | ResultTimeout\n  | ResultCancel\n  | ResultUnknown\n\n// other types for oldest usage\ninterface DispatchAsyncResultSuccess\u003cT = any\u003e {\n  success: true\n  result: T\n}\ninterface DispatchAsyncResultError {\n  success: false\n  error: Error\n}\nexport type DispatchAsyncResult\u003cT = any\u003e =\n  | DispatchAsyncResultSuccess\u003cT\u003e\n  | DispatchAsyncResultError\n```\n\n## Hire an expert!\n\nLooking for a ReactNative freelance expert with more than 14 years experience? Contact me from my [website](https://xaviercarpentier.com)!\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fxcarpentier%2Freact-redux-dispatch-async","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fxcarpentier%2Freact-redux-dispatch-async","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fxcarpentier%2Freact-redux-dispatch-async/lists"}