import { useCallback } from "react" ; import TaskInstance from "./instance" ; import perform from "./perform" ; import { useTaskStateReducer , useDerivedState } from "./state" ; import { AnyFunction , UseTaskConfig , UseTaskResult } from "./types" ; import useIsMounted from "./hooks/use-is-mounted" ; import useUnmountWithState from "./hooks/use-unmount-with-state" ; import { cancelAllInstances } from "./utils/cancellation" ; export default function useTask < T extends AnyFunction > ( taskDefinition , { keep = "last" } = { } ) { const [ taskState , dispatch ] = useTaskStateReducer < T > ( keep ) ; if ( keep !== taskState . keep ) { console . warn ( "Cannot dynamically change how to handle concurrent tasks" ) ; } const isMountedRef = useIsMounted ( ) ; const derivedState = useDerivedState < T > ( taskState ) ; useUnmountWithState ( taskState , currentTaskState => { cancelAllInstances ( currentTaskState . instances ) ; } ) ; const runCallback = useCallback ( ( ... args ) => { const instance = new TaskInstance ( taskDefinition , action => { if ( isMountedRef . current ) { dispatch ( action ) ; } } ) ; if ( keep === "first" && derivedState . isRunning ) { instance . abortController . abort ( ) ; return instance ; } if ( keep === "last" && derivedState . isRunning ) { cancelAllInstances ( taskState . instances ) ; } perform ( instance , args as Parameters < T > ) ; return instance ; } , [ derivedState . isRunning , keep , taskDefinition , taskState . instances , dispatch , isMountedRef ] ) ; return [ runCallback , derivedState ] ; } export { default as useTaskWithSignal } from "./with-signal" ; export { default as timeout } from "./utils/timeout" ; export { isAbortError } from "./utils/abort-error" ;