@@ -21,49 +21,68 @@ const useAsync = (arg1, arg2) => {
2121 options ,
2222 init
2323 )
24- const dispatch = dispatcher
25- ? action => dispatcher ( action , dispatchMiddleware ( _dispatch ) , options )
26- : dispatchMiddleware ( _dispatch )
27-
28- const getMeta = meta => ( { counter : counter . current , debugLabel : options . debugLabel , ...meta } )
24+ const dispatch = useCallback (
25+ dispatcher
26+ ? action => dispatcher ( action , dispatchMiddleware ( _dispatch ) , lastOptions . current )
27+ : dispatchMiddleware ( _dispatch ) ,
28+ [ dispatcher ]
29+ )
2930
30- const setData = ( data , callback = noop ) => {
31- if ( isMounted . current ) {
32- dispatch ( { type : actionTypes . fulfill , payload : data , meta : getMeta ( ) } )
33- callback ( )
34- }
35- return data
36- }
31+ const { debugLabel } = options
32+ const getMeta = useCallback ( meta => ( { counter : counter . current , debugLabel, ...meta } ) , [
33+ debugLabel ,
34+ ] )
35+
36+ const setData = useCallback (
37+ ( data , callback = noop ) => {
38+ if ( isMounted . current ) {
39+ dispatch ( { type : actionTypes . fulfill , payload : data , meta : getMeta ( ) } )
40+ callback ( )
41+ }
42+ return data
43+ } ,
44+ [ dispatch , getMeta ]
45+ )
3746
38- const setError = ( error , callback = noop ) => {
39- if ( isMounted . current ) {
40- dispatch ( { type : actionTypes . reject , payload : error , error : true , meta : getMeta ( ) } )
41- callback ( )
42- }
43- return error
44- }
47+ const setError = useCallback (
48+ ( error , callback = noop ) => {
49+ if ( isMounted . current ) {
50+ dispatch ( { type : actionTypes . reject , payload : error , error : true , meta : getMeta ( ) } )
51+ callback ( )
52+ }
53+ return error
54+ } ,
55+ [ dispatch , getMeta ]
56+ )
4557
4658 const { onResolve, onReject } = options
47- const handleResolve = count => data =>
48- count === counter . current && setData ( data , ( ) => onResolve && onResolve ( data ) )
49- const handleReject = count => error =>
50- count === counter . current && setError ( error , ( ) => onReject && onReject ( error ) )
51-
52- const start = promiseFn => {
53- if ( "AbortController" in globalScope ) {
54- abortController . current . abort ( )
55- abortController . current = new globalScope . AbortController ( )
56- }
57- counter . current ++
58- return new Promise ( ( resolve , reject ) => {
59- if ( ! isMounted . current ) return
60- const executor = ( ) => promiseFn ( ) . then ( resolve , reject )
61- dispatch ( { type : actionTypes . start , payload : executor , meta : getMeta ( ) } )
62- } )
63- }
59+ const handleResolve = useCallback (
60+ count => data => count === counter . current && setData ( data , ( ) => onResolve && onResolve ( data ) ) ,
61+ [ setData , onResolve ]
62+ )
63+ const handleReject = useCallback (
64+ count => err => count === counter . current && setError ( err , ( ) => onReject && onReject ( err ) ) ,
65+ [ setError , onReject ]
66+ )
67+
68+ const start = useCallback (
69+ promiseFn => {
70+ if ( "AbortController" in globalScope ) {
71+ abortController . current . abort ( )
72+ abortController . current = new globalScope . AbortController ( )
73+ }
74+ counter . current ++
75+ return new Promise ( ( resolve , reject ) => {
76+ if ( ! isMounted . current ) return
77+ const executor = ( ) => promiseFn ( ) . then ( resolve , reject )
78+ dispatch ( { type : actionTypes . start , payload : executor , meta : getMeta ( ) } )
79+ } )
80+ } ,
81+ [ dispatch , getMeta ]
82+ )
6483
6584 const { promise, promiseFn, initialValue } = options
66- const load = ( ) => {
85+ const load = useCallback ( ( ) => {
6786 if ( promise ) {
6887 return start ( ( ) => promise ) . then (
6988 handleResolve ( counter . current ) ,
@@ -77,26 +96,36 @@ const useAsync = (arg1, arg2) => {
7796 handleReject ( counter . current )
7897 )
7998 }
80- }
99+ } , [ start , promise , promiseFn , initialValue , handleResolve , handleReject ] )
81100
82101 const { deferFn } = options
83- const run = ( ...args ) => {
84- if ( deferFn ) {
85- lastArgs . current = args
86- return start ( ( ) => deferFn ( args , lastOptions . current , abortController . current ) ) . then (
87- handleResolve ( counter . current ) ,
88- handleReject ( counter . current )
89- )
90- }
91- }
102+ const run = useCallback (
103+ ( ...args ) => {
104+ if ( deferFn ) {
105+ lastArgs . current = args
106+ return start ( ( ) => deferFn ( args , lastOptions . current , abortController . current ) ) . then (
107+ handleResolve ( counter . current ) ,
108+ handleReject ( counter . current )
109+ )
110+ }
111+ } ,
112+ [ start , deferFn , handleResolve , handleReject ]
113+ )
114+
115+ const reload = useCallback ( ( ) => {
116+ return lastArgs . current ? run ( ...lastArgs . current ) : load ( )
117+ } , [ run , load ] )
92118
93- const cancel = ( ) => {
94- options . onCancel && options . onCancel ( )
119+ const { onCancel } = options
120+ const cancel = useCallback ( ( ) => {
121+ onCancel && onCancel ( )
95122 counter . current ++
96123 abortController . current . abort ( )
97124 isMounted . current && dispatch ( { type : actionTypes . cancel , meta : getMeta ( ) } )
98- }
125+ } , [ onCancel , dispatch , getMeta ] )
99126
127+ /* These effects should only be triggered on changes to specific props */
128+ /* eslint-disable react-hooks/exhaustive-deps */
100129 const { watch, watchFn } = options
101130 useEffect ( ( ) => {
102131 if ( watchFn && lastOptions . current && watchFn ( options , lastOptions . current ) ) load ( )
@@ -108,19 +137,20 @@ const useAsync = (arg1, arg2) => {
108137 } , [ promise , promiseFn , watch ] )
109138 useEffect ( ( ) => ( ) => ( isMounted . current = false ) , [ ] )
110139 useEffect ( ( ) => ( ) => cancel ( ) , [ ] )
140+ /* eslint-enable react-hooks/exhaustive-deps */
111141
112142 useDebugValue ( state , ( { status } ) => `[${ counter . current } ] ${ status } ` )
113143
114144 return useMemo (
115145 ( ) => ( {
116146 ...state ,
117- cancel,
118147 run,
119- reload : ( ) => ( lastArgs . current ? run ( ...lastArgs . current ) : load ( ) ) ,
148+ reload,
149+ cancel,
120150 setData,
121151 setError,
122152 } ) ,
123- [ state , deferFn , onResolve , onReject , dispatcher , reducer ]
153+ [ state , run , reload , cancel , setData , setError ]
124154 )
125155}
126156
@@ -138,11 +168,12 @@ const useAsyncFetch = (input, init, { defer, json, ...options } = {}) => {
138168 const doFetch = ( input , init ) => globalScope . fetch ( input , init ) . then ( parseResponse ( accept , json ) )
139169 const isDefer = defer === true || ~ [ "POST" , "PUT" , "PATCH" , "DELETE" ] . indexOf ( method )
140170 const fn = defer === false || ! isDefer ? "promiseFn" : "deferFn"
171+ const identity = JSON . stringify ( { input, init } )
141172 const state = useAsync ( {
142173 ...options ,
143174 [ fn ] : useCallback (
144175 ( _ , props , ctrl ) => doFetch ( input , { signal : ctrl ? ctrl . signal : props . signal , ...init } ) ,
145- [ JSON . stringify ( input ) , JSON . stringify ( init ) ]
176+ [ identity ] // eslint-disable-line react-hooks/exhaustive-deps
146177 ) ,
147178 } )
148179 useDebugValue ( state , ( { counter, status } ) => `[${ counter } ] ${ status } ` )
0 commit comments