UNPKG

use-reducer-async

Version:
1 lines 5.69 kB
{"version":3,"file":"index.modern.js","sources":["../src/index.ts"],"sourcesContent":["import {\n useCallback,\n useEffect,\n useLayoutEffect,\n useReducer,\n useRef,\n useState,\n Dispatch,\n Reducer,\n ReducerState,\n} from 'react';\n\ntype ReducerAction<R extends Reducer<any, any>> = R extends Reducer<any, infer A> ? A : never;\n\nconst isClient = (\n typeof window !== 'undefined'\n && !/ServerSideRendering/.test(window.navigator && window.navigator.userAgent)\n);\n\nconst useIsomorphicLayoutEffect = isClient ? useLayoutEffect : useEffect;\n\nconst useAbortSignal = () => {\n const [controller, setController] = useState(() => new AbortController());\n const lastController = useRef(controller);\n useEffect(() => {\n const abort = () => {\n lastController.current.abort();\n lastController.current = new AbortController();\n setController(lastController.current);\n };\n return abort;\n }, []);\n return controller.signal;\n};\n\nexport type AsyncActionHandlers<\n R extends Reducer<any, any>,\n AsyncAction extends { type: string }\n> = {\n [T in AsyncAction['type']]: AsyncAction extends infer A ? A extends {\n type: T;\n } ? (s: {\n dispatch: Dispatch<AsyncAction | ReducerAction<R>>;\n getState: () => ReducerState<R>;\n signal: AbortSignal;\n }) => (a: A) => Promise<void> : never : never;\n};\n\nexport function useReducerAsync<\n R extends Reducer<any, any>,\n I,\n AsyncAction extends { type: string },\n ExportAction extends AsyncAction | ReducerAction<R> = AsyncAction | ReducerAction<R>\n>(\n reducer: R,\n initializerArg: I,\n initializer: (arg: I) => ReducerState<R>,\n asyncActionHandlers: AsyncActionHandlers<R, AsyncAction>,\n): [ReducerState<R>, Dispatch<ExportAction>];\n\n/**\n * useReducer with async actions\n * @example\n * import { useReducerAsync } from 'use-reducer-async';\n *\n * const asyncActionHandlers = {\n * SLEEP: ({ dispatch, getState, signal }) => async (action) => {\n * dispatch({ type: 'START_SLEEP' });\n * await new Promise(r => setTimeout(r, action.ms));\n * dispatch({ type: 'END_SLEEP' });\n * },\n * FETCH: ({ dispatch, getState, signal }) => async (action) => {\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 * };\n * const [state, dispatch] = useReducerAsync(reducer, initialState, asyncActionHandlers);\n */\nexport function useReducerAsync<\n R extends Reducer<any, any>,\n AsyncAction extends { type: string },\n ExportAction extends AsyncAction | ReducerAction<R> = AsyncAction | ReducerAction<R>\n>(\n reducer: R,\n initialState: ReducerState<R>,\n asyncActionHandlers: AsyncActionHandlers<R, AsyncAction>,\n): [ReducerState<R>, Dispatch<ExportAction>];\n\nexport function useReducerAsync<\n R extends Reducer<any, any>,\n I,\n AsyncAction extends { type: string },\n ExportAction extends AsyncAction | ReducerAction<R> = AsyncAction | ReducerAction<R>\n>(\n reducer: R,\n initializerArg: I | ReducerState<R>,\n initializer: unknown,\n asyncActionHandlers?: AsyncActionHandlers<R, AsyncAction>,\n): [ReducerState<R>, Dispatch<ExportAction>] {\n const signal = useAbortSignal();\n const aaHandlers = (\n asyncActionHandlers || initializer\n ) as AsyncActionHandlers<R, AsyncAction>;\n const [state, dispatch] = useReducer(\n reducer,\n initializerArg as any,\n asyncActionHandlers && initializer as any,\n );\n const lastState = useRef(state);\n useIsomorphicLayoutEffect(() => {\n lastState.current = state;\n }, [state]);\n const getState = useCallback((() => lastState.current), []);\n const wrappedDispatch = useCallback((action: AsyncAction | ReducerAction<R>) => {\n const { type } = (action || {}) as { type?: AsyncAction['type'] };\n const aaHandler = (\n (type && aaHandlers[type]) || null\n ) as (typeof action extends AsyncAction ? (s: {\n dispatch: Dispatch<AsyncAction | ReducerAction<R>>;\n getState: () => ReducerState<R>;\n signal: AbortSignal;\n }) => (a: typeof action) => Promise<void> : null);\n if (aaHandler) {\n aaHandler({ dispatch: wrappedDispatch, getState, signal })(action as AsyncAction);\n } else {\n dispatch(action as ReducerAction<R>);\n }\n }, [aaHandlers, getState, signal]);\n return [state, wrappedDispatch];\n}\n"],"names":["useIsomorphicLayoutEffect","window","test","navigator","userAgent","useEffect","useLayoutEffect","useReducerAsync","reducer","initializerArg","initializer","asyncActionHandlers","signal","controller","setController","useState","AbortController","lastController","useRef","current","abort","useAbortSignal","aaHandlers","state","dispatch","useReducer","lastState","getState","useCallback","wrappedDispatch","action","type","aaHandler"],"mappings":"kHAcA,MAKMA,EAJc,oBAAlBC,QACI,sBAAsBC,KAAKD,OAAOE,WAAaF,OAAOE,UAAUC,WAGPC,EAAlBC,EA2E7BC,SAAAA,EAMdC,EACAC,EACAC,EACAC,GAEA,MAAMC,EApFe,MACrB,MAAOC,EAAYC,GAAiBC,EAAS,IAAM,IAAIC,iBACnCC,EAAGC,EAAOL,GAS9B,OARAR,EAAU,IACM,KACZY,EAAeE,QAAQC,QACvBH,EAAeE,QAAU,IAAzBH,gBACAF,EAAcG,EAAeE,UAG9B,IACIN,EAAWD,QAyEHS,GACCC,EACdX,GAAuBD,GAElBa,EAAOC,GAAYC,EACxBjB,EACAC,EACAE,GAAuBD,GAEVgB,EAAGR,EAAOK,GACzBvB,EAA0B,KACxB0B,EAAUP,QAAUI,GACnB,CAACA,IACJ,MAAcI,EAAGC,EAAa,IAAMF,EAAUP,QAAU,IAClDU,EAAkBD,EAAaE,IACnC,MAAMC,KAAEA,GAAUD,GAAU,GACbE,EACZD,GAAQT,EAAWS,IAAU,KAM5BC,EACFA,EAAU,CAAER,SAAUK,EAAiBF,SAAAA,EAAUf,OAAAA,GAAjDoB,CAA2DF,GAE3DN,EAASM,IAEV,CAACR,EAAYK,EAAUf,IAC1B,MAAO,CAACW,EAAOM"}