react-async-reducer
v1.0.2
Published
this package introduces a hook that functions as an asynchronus reducer (useAsyncReducer), it is react and typescript friendly
Readme
🌀 useAsyncReducer
Minimalist hook for handling asynchronous reducers in React with TypeScript. Perfect for scenarios where state depends on async operations such as API calls, heavy computations, or chained effects.
📦 Installation
npm install use-async-reducer
# or
yarn add use-async-reducer⚙️ Requirements
- React ≥ 16.8 (hooks enabled)
- TypeScript ≥ 4.5
- Compatible with Vite, Next.js, CRA, Tauri, Electron, and more.
🔍 What problem does it solve?
React does not natively support asynchronous reducers. useAsyncReducer lets you use async logic inside your reducer without breaking the declarative flow. It's useful when:
- The new state depends on a promise (fetch, calculation, delay).
- You want to keep the semantics of
dispatch(action)without external effects. - You want to encapsulate complex logic without mixing
useEffectanduseReducer.
🛠️ API
function useAsyncReducer<State, Action>(
reducer: (state: State, action: Action) => Promise<State>,
initialState: State
): {
state: State;
dispatch: (action: Action) => void;
}Parameters
reducer: An async function that receives the current state and an action, and returns a promise with the new state.initialState: The initial state for the reducer.
Returns
state: The current state.dispatch: Function to dispatch actions. Does not return anything, but updates the state when the promise resolves.
🧪 Full Example
import useAsyncReducer from 'use-async-reducer'
// State and Action types
type State = { count: number }
type Action = { type: 'increment' | 'decrement' }
// Async reducer function
const asyncReducer = async (state: State, action: Action): Promise<State> => {
switch (action.type) {
case 'increment':
await new Promise(res => setTimeout(res, 300)) // Simulate delay
return { count: state.count + 1 }
case 'decrement':
return { count: state.count - 1 }
default:
return state
}
}
// Usage in a component
const Counter = () => {
const { state, dispatch } = useAsyncReducer(asyncReducer, { count: 0 })
return (
<div>
<p>Count: {state.count}</p>
<button onClick={() => dispatch({ type: 'increment' })}>+</button>
<button onClick={() => dispatch({ type: 'decrement' })}>-</button>
</div>
)
}