overleaf/services/web/frontend/js/shared/hooks/use-async.ts
Alexandre Bourdin a0fabee3b4 Merge pull request #9245 from overleaf/integration-project-dashboard-react-migration
[Integration branch] Project Dashboard React Migration

GitOrigin-RevId: 3c3db39109a8137c57995f5f7c0ff8c800f04c4e
2022-09-14 08:04:03 +00:00

82 lines
1.9 KiB
TypeScript

import * as React from 'react'
import useSafeDispatch from './use-safe-dispatch'
import { Nullable } from '../../../../types/utils'
import { FetchError } from '../../infrastructure/fetch-json'
type State<T, E> = {
status: 'idle' | 'pending' | 'resolved' | 'rejected'
data: Nullable<T>
error: Nullable<E>
}
type Action<T, E> = Partial<State<T, E>>
const defaultInitialState: State<null, null> = {
status: 'idle',
data: null,
error: null,
}
function useAsync<T = any, E extends Error | FetchError = Error>(
initialState?: Partial<State<T, E>>
) {
const initialStateRef = React.useRef({
...defaultInitialState,
...initialState,
})
const [{ status, data, error }, setState] = React.useReducer(
(state: State<T, E>, action: Action<T, E>) => ({ ...state, ...action }),
initialStateRef.current
)
const safeSetState = useSafeDispatch(setState)
const setData = React.useCallback(
(data: Nullable<T>) => safeSetState({ data, status: 'resolved' }),
[safeSetState]
)
const setError = React.useCallback(
(error: Nullable<E>) => safeSetState({ error, status: 'rejected' }),
[safeSetState]
)
const reset = React.useCallback(
() => safeSetState(initialStateRef.current),
[safeSetState]
)
const runAsync = React.useCallback(
(promise: Promise<T>) => {
safeSetState({ status: 'pending' })
return promise.then(
data => {
setData(data)
return data
},
error => {
setError(error)
return Promise.reject(error)
}
)
},
[safeSetState, setData, setError]
)
return {
isIdle: status === 'idle',
isLoading: status === 'pending',
isError: status === 'rejected',
isSuccess: status === 'resolved',
setData,
setError,
error,
status,
data,
runAsync,
reset,
}
}
export default useAsync
export type UseAsyncReturnType = ReturnType<typeof useAsync>