Created
June 30, 2023 13:53
-
-
Save alirezaseif28/66efa18cbf0b6d981fa3496c5ed4113e to your computer and use it in GitHub Desktop.
useReducer in React is Async
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React, { useEffect, useMemo, useReducer } from "react"; | |
export type Reducer<State, Action> = (state: State, action: Action) => State; | |
export type AsyncReducer<State, Action> = ( | |
state: State, | |
action: Action | |
) => { state: State; effects: Array<Lazy<Promise<Array<Action>>>> }; | |
export function useAsyncReducer<State, Action>( | |
initialState: State, | |
asyncReducer: AsyncReducer<State, Action> | |
): readonly [State, React.Dispatch<Action>] { | |
const memoReducer = useMemo< | |
Reducer< | |
{ state: State; effects: Array<Lazy<Promise<Array<Action>>>> }, | |
Action | |
> | |
>( | |
() => | |
({ state }, action: Action) => | |
asyncReducer(state, action), | |
[asyncReducer] | |
); | |
const [{ state, effects }, dispatch] = useReducer(memoReducer, { | |
state: initialState, | |
effects: [], | |
}); | |
useEffect(() => { | |
const runEffects = async () => { | |
for (let effect of effects) { | |
const actions = await effect(); | |
for (let action of actions) { | |
dispatch(action); | |
} | |
} | |
}; | |
runEffects(); | |
}, [effects]); | |
return [state, dispatch] as const; | |
} | |
export function noEffects<State>(state: State) { | |
return { state, effects: [] }; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment