Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/dai-shi/use-reducer-async
React useReducer with async actions
https://github.com/dai-shi/use-reducer-async
async async-actions dispatch react react-hooks reactjs use-reducer
Last synced: about 18 hours ago
JSON representation
React useReducer with async actions
- Host: GitHub
- URL: https://github.com/dai-shi/use-reducer-async
- Owner: dai-shi
- License: mit
- Created: 2019-10-22T12:05:59.000Z (about 5 years ago)
- Default Branch: main
- Last Pushed: 2023-03-15T01:19:26.000Z (almost 2 years ago)
- Last Synced: 2025-01-05T00:13:17.161Z (8 days ago)
- Topics: async, async-actions, dispatch, react, react-hooks, reactjs, use-reducer
- Language: TypeScript
- Homepage: https://www.npmjs.com/package/use-reducer-async
- Size: 2.18 MB
- Stars: 180
- Watchers: 7
- Forks: 9
- Open Issues: 9
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- License: LICENSE
Awesome Lists containing this project
- fucking-awesome-react-hooks - `use-reducer-async`
- awesome-react-hooks-cn - `use-reducer-async`
- awesome-react-hooks - `use-reducer-async`
- awesome-react-hooks - `use-reducer-async`
README
# use-reducer-async
[![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)
[![npm](https://img.shields.io/npm/v/use-reducer-async)](https://www.npmjs.com/package/use-reducer-async)
[![size](https://img.shields.io/bundlephobia/minzip/use-reducer-async)](https://bundlephobia.com/result?p=use-reducer-async)
[![discord](https://img.shields.io/discord/627656437971288081)](https://discord.gg/MrQdmzd)React useReducer with async actions
## Introduction
React useReducer doesn't support async actions natively.
Unlike Redux, there's no middleware interface, but hooks are composable.This is a tiny library to extend useReducer's dispatch
so that dispatching async actions invoke async functions.## Install
```bash
npm install use-reducer-async
```## Usage
```javascript
import { useReducerAsync } from "use-reducer-async";
const initialState = {
sleeping: false,
};const reducer = (state, action) => {
switch (action.type) {
case 'START_SLEEP': return { ...state, sleeping: true };
case 'END_SLEEP': return { ...state, sleeping: false };
default: throw new Error('no such action type');
}
};const asyncActionHandlers = {
SLEEP: ({ dispatch }) => async (action) => {
dispatch({ type: 'START_SLEEP' });
await new Promise(r => setTimeout(r, action.ms));
dispatch({ type: 'END_SLEEP' });
},
};const Component = () => {
const [state, dispatch] = useReducerAsync(reducer, initialState, asyncActionHandlers);
return (
{state.sleeping ? 'Sleeping' : 'Idle'}
dispatch({ type: 'SLEEP', ms: 1000 })}>Click
);
};
```### Notes for abortability
All async action handlers receive `signal` in the argument.
Refer [`examples/04_abort/src`](./examples/04\_abort/src) for the usage.Note: The implementation depends on [AbortController](https://developer.mozilla.org/en-US/docs/Web/API/AbortController) in the DOM spec.
If you are using an environment that doesn't have AbortController (for example IE11), you need a polyfill:
[1](https://github.com/mo/abortcontroller-polyfill)
[2](https://github.com/mysticatea/abort-controller)## API
### useReducerAsync
useReducer with async actions
#### Parameters
* `reducer` **R**
* `initialState` **ReducerState\**
* `asyncActionHandlers` **AsyncActionHandlers\**#### Examples
```javascript
import { useReducerAsync } from 'use-reducer-async';const asyncActionHandlers = {
SLEEP: ({ dispatch, getState, signal }) => async (action) => {
dispatch({ type: 'START_SLEEP' });
await new Promise(r => setTimeout(r, action.ms));
dispatch({ type: 'END_SLEEP' });
},
FETCH: ({ dispatch, getState, signal }) => async (action) => {
dispatch({ type: 'START_FETCH' });
try {
const response = await fetch(action.url);
const data = await response.json();
dispatch({ type: 'FINISH_FETCH', data });
} catch (error) {
dispatch({ type: 'ERROR_FETCH', error });
}
},
};
const [state, dispatch] = useReducerAsync(reducer, initialState, asyncActionHandlers);
```Returns **\[ReducerState\, Dispatch\]**
## Examples
The [examples](examples) folder contains working examples.
You can run one of them with```bash
PORT=8080 npm run examples:01_minimal
```and open in your web browser.
You can also try them in codesandbox.io:
[01](https://codesandbox.io/s/github/dai-shi/use-reducer-async/tree/main/examples/01\_minimal)
[02](https://codesandbox.io/s/github/dai-shi/use-reducer-async/tree/main/examples/02\_typescript)
[03](https://codesandbox.io/s/github/dai-shi/use-reducer-async/tree/main/examples/03\_getstate)
[04](https://codesandbox.io/s/github/dai-shi/use-reducer-async/tree/main/examples/04\_abort)## Blogs
* [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/)