1
- import { useCallback , useDebugValue , useEffect , useMemo , useRef , useState } from "react"
1
+ import { useCallback , useDebugValue , useEffect , useMemo , useRef , useReducer } from "react"
2
+ import { actions , init , reducer } from "./reducer"
3
+
4
+ const noop = ( ) => { }
2
5
3
6
const useAsync = ( arg1 , arg2 ) => {
4
7
const counter = useRef ( 0 )
5
8
const isMounted = useRef ( true )
6
9
const lastArgs = useRef ( undefined )
7
10
const prevOptions = useRef ( undefined )
8
- const abortController = useRef ( { abort : ( ) => { } } )
11
+ const abortController = useRef ( { abort : noop } )
9
12
10
13
const options = typeof arg1 === "function" ? { ...arg2 , promiseFn : arg1 } : arg1
11
14
const { promise, promiseFn, deferFn, initialValue, onResolve, onReject, watch, watchFn } = options
12
15
13
- const [ state , setState ] = useState ( {
14
- data : initialValue instanceof Error ? undefined : initialValue ,
15
- error : initialValue instanceof Error ? initialValue : undefined ,
16
- startedAt : promise || promiseFn ? new Date ( ) : undefined ,
17
- finishedAt : initialValue ? new Date ( ) : undefined ,
18
- } )
16
+ const [ state , dispatch ] = useReducer ( reducer , options , init )
19
17
20
- const handleData = ( data , callback = ( ) => { } ) => {
18
+ const setData = ( data , callback = noop ) => {
21
19
if ( isMounted . current ) {
22
- setState ( state => ( { ... state , data , error : undefined , finishedAt : new Date ( ) } ) )
23
- callback ( data )
20
+ dispatch ( { type : actions . fulfill , payload : data } )
21
+ callback ( )
24
22
}
25
23
return data
26
24
}
27
25
28
- const handleError = ( error , callback = ( ) => { } ) => {
26
+ const setError = ( error , callback = noop ) => {
29
27
if ( isMounted . current ) {
30
- setState ( state => ( { ... state , error, finishedAt : new Date ( ) } ) )
31
- callback ( error )
28
+ dispatch ( { type : actions . reject , payload : error , error : true } )
29
+ callback ( )
32
30
}
33
31
return error
34
32
}
35
33
36
- const handleResolve = count => data => count === counter . current && handleData ( data , onResolve )
37
- const handleReject = count => error => count === counter . current && handleError ( error , onReject )
34
+ const handleResolve = count => data =>
35
+ count === counter . current && setData ( data , ( ) => onResolve && onResolve ( data ) )
36
+ const handleReject = count => error =>
37
+ count === counter . current && setError ( error , ( ) => onReject && onReject ( error ) )
38
38
39
39
const start = ( ) => {
40
40
if ( "AbortController" in window ) {
41
41
abortController . current . abort ( )
42
42
abortController . current = new window . AbortController ( )
43
43
}
44
44
counter . current ++
45
- setState ( state => ( {
46
- ...state ,
47
- startedAt : new Date ( ) ,
48
- finishedAt : undefined ,
49
- } ) )
45
+ dispatch ( { type : actions . start , meta : { counter : counter . current } } )
50
46
}
51
47
52
48
const load = ( ) => {
@@ -79,7 +75,7 @@ const useAsync = (arg1, arg2) => {
79
75
const cancel = ( ) => {
80
76
counter . current ++
81
77
abortController . current . abort ( )
82
- setState ( state => ( { ... state , startedAt : undefined } ) )
78
+ dispatch ( { type : actions . cancel , meta : { counter : counter . current } } )
83
79
}
84
80
85
81
useEffect ( ( ) => {
@@ -104,14 +100,11 @@ const useAsync = (arg1, arg2) => {
104
100
return useMemo (
105
101
( ) => ( {
106
102
...state ,
107
- initialValue,
108
- isLoading : state . startedAt && ( ! state . finishedAt || state . finishedAt < state . startedAt ) ,
109
- counter : counter . current ,
110
103
run,
111
104
reload : ( ) => ( lastArgs . current ? run ( ...lastArgs . current ) : load ( ) ) ,
112
105
cancel,
113
- setData : handleData ,
114
- setError : handleError ,
106
+ setData,
107
+ setError,
115
108
} ) ,
116
109
[ state ]
117
110
)
@@ -152,5 +145,5 @@ const unsupported = () => {
152
145
)
153
146
}
154
147
155
- export default ( useState ? useAsync : unsupported )
156
- export const useFetch = useState ? useAsyncFetch : unsupported
148
+ export default ( useEffect ? useAsync : unsupported )
149
+ export const useFetch = useEffect ? useAsyncFetch : unsupported
0 commit comments