{"id":13450850,"url":"https://github.com/dai-shi/use-reducer-async","last_synced_at":"2025-04-05T08:03:52.541Z","repository":{"id":35190620,"uuid":"216804164","full_name":"dai-shi/use-reducer-async","owner":"dai-shi","description":"React useReducer with async actions","archived":false,"fork":false,"pushed_at":"2023-03-15T01:19:26.000Z","size":2286,"stargazers_count":180,"open_issues_count":9,"forks_count":9,"subscribers_count":6,"default_branch":"main","last_synced_at":"2025-03-29T07:03:58.726Z","etag":null,"topics":["async","async-actions","dispatch","react","react-hooks","reactjs","use-reducer"],"latest_commit_sha":null,"homepage":"https://www.npmjs.com/package/use-reducer-async","language":"TypeScript","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/dai-shi.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2019-10-22T12:05:59.000Z","updated_at":"2024-12-19T05:31:27.000Z","dependencies_parsed_at":"2024-01-07T18:23:50.479Z","dependency_job_id":null,"html_url":"https://github.com/dai-shi/use-reducer-async","commit_stats":{"total_commits":82,"total_committers":5,"mean_commits":16.4,"dds":"0.13414634146341464","last_synced_commit":"281b2e8693eaa6cfe1e0383e08ab570bd80b8566"},"previous_names":[],"tags_count":6,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dai-shi%2Fuse-reducer-async","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dai-shi%2Fuse-reducer-async/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dai-shi%2Fuse-reducer-async/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dai-shi%2Fuse-reducer-async/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dai-shi","download_url":"https://codeload.github.com/dai-shi/use-reducer-async/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247305932,"owners_count":20917208,"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","dispatch","react","react-hooks","reactjs","use-reducer"],"created_at":"2024-07-31T07:00:39.328Z","updated_at":"2025-04-05T08:03:52.523Z","avatar_url":"https://github.com/dai-shi.png","language":"TypeScript","funding_links":[],"categories":["Packages"],"sub_categories":[],"readme":"# use-reducer-async\n\n[![CI](https://img.shields.io/github/workflow/status/dai-shi/use-reducer-async/CI)](https://github.com/dai-shi/use-reducer-async/actions?query=workflow%3ACI)\n[![npm](https://img.shields.io/npm/v/use-reducer-async)](https://www.npmjs.com/package/use-reducer-async)\n[![size](https://img.shields.io/bundlephobia/minzip/use-reducer-async)](https://bundlephobia.com/result?p=use-reducer-async)\n[![discord](https://img.shields.io/discord/627656437971288081)](https://discord.gg/MrQdmzd)\n\nReact useReducer with async actions\n\n## Introduction\n\nReact useReducer doesn't support async actions natively.\nUnlike Redux, there's no middleware interface, but hooks are composable.\n\nThis is a tiny library to extend useReducer's dispatch\nso that dispatching async actions invoke async functions.\n\n## Install\n\n```bash\nnpm install use-reducer-async\n```\n\n## Usage\n\n```javascript\n\nimport { useReducerAsync } from \"use-reducer-async\";\n\nconst initialState = {\n  sleeping: false,\n};\n\nconst reducer = (state, action) =\u003e {\n  switch (action.type) {\n    case 'START_SLEEP': return { ...state, sleeping: true };\n    case 'END_SLEEP': return { ...state, sleeping: false };\n    default: throw new Error('no such action type');\n  }\n};\n\nconst asyncActionHandlers = {\n  SLEEP: ({ dispatch }) =\u003e async (action) =\u003e {\n    dispatch({ type: 'START_SLEEP' });\n    await new Promise(r =\u003e setTimeout(r, action.ms));\n    dispatch({ type: 'END_SLEEP' });\n  },\n};\n\nconst Component = () =\u003e {\n  const [state, dispatch] = useReducerAsync(reducer, initialState, asyncActionHandlers);\n  return (\n    \u003cdiv\u003e\n      \u003cspan\u003e{state.sleeping ? 'Sleeping' : 'Idle'}\u003c/span\u003e\n      \u003cbutton type=\"button\" onClick={() =\u003e dispatch({ type: 'SLEEP', ms: 1000 })}\u003eClick\u003c/button\u003e\n    \u003c/div\u003e\n  );\n};\n```\n\n### Notes for abortability\n\nAll async action handlers receive `signal` in the argument.\nRefer [`examples/04_abort/src`](./examples/04\\_abort/src) for the usage.\n\nNote: The implementation depends on [AbortController](https://developer.mozilla.org/en-US/docs/Web/API/AbortController) in the DOM spec.\nIf you are using an environment that doesn't have AbortController (for example IE11), you need a polyfill:\n[1](https://github.com/mo/abortcontroller-polyfill)\n[2](https://github.com/mysticatea/abort-controller)\n\n## API\n\n\u003c!-- Generated by documentation.js. Update this documentation by updating the source code. --\u003e\n\n### useReducerAsync\n\nuseReducer with async actions\n\n#### Parameters\n\n*   `reducer` **R** \n*   `initialState` **ReducerState\\\u003cR\u003e** \n*   `asyncActionHandlers` **AsyncActionHandlers\\\u003cR, AsyncAction\u003e** \n\n#### Examples\n\n```javascript\nimport { useReducerAsync } from 'use-reducer-async';\n\nconst asyncActionHandlers = {\n  SLEEP: ({ dispatch, getState, signal }) =\u003e async (action) =\u003e {\n    dispatch({ type: 'START_SLEEP' });\n    await new Promise(r =\u003e setTimeout(r, action.ms));\n    dispatch({ type: 'END_SLEEP' });\n  },\n  FETCH: ({ dispatch, getState, signal }) =\u003e async (action) =\u003e {\n    dispatch({ type: 'START_FETCH' });\n    try {\n      const response = await fetch(action.url);\n      const data = await response.json();\n      dispatch({ type: 'FINISH_FETCH', data });\n    } catch (error) {\n      dispatch({ type: 'ERROR_FETCH', error });\n    }\n  },\n};\nconst [state, dispatch] = useReducerAsync(reducer, initialState, asyncActionHandlers);\n```\n\nReturns **\\[ReducerState\\\u003cR\u003e, Dispatch\\\u003cExportAction\u003e]** \n\n## Examples\n\nThe [examples](examples) folder contains working examples.\nYou can run one of them with\n\n```bash\nPORT=8080 npm run examples:01_minimal\n```\n\nand open \u003chttp://localhost:8080\u003e in your web browser.\n\nYou can also try them in codesandbox.io:\n[01](https://codesandbox.io/s/github/dai-shi/use-reducer-async/tree/main/examples/01\\_minimal)\n[02](https://codesandbox.io/s/github/dai-shi/use-reducer-async/tree/main/examples/02\\_typescript)\n[03](https://codesandbox.io/s/github/dai-shi/use-reducer-async/tree/main/examples/03\\_getstate)\n[04](https://codesandbox.io/s/github/dai-shi/use-reducer-async/tree/main/examples/04\\_abort)\n\n## Blogs\n\n*   [How to Handle Async Actions for Global State With React Hooks and Context](https://blog.axlight.com/posts/how-to-handle-async-actions-for-global-state-with-react-hooks-and-context/)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdai-shi%2Fuse-reducer-async","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdai-shi%2Fuse-reducer-async","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdai-shi%2Fuse-reducer-async/lists"}