1- import { useEffect , useMemo , useState } from 'react'
1+ import { useEffect , useMemo , useRef , useState } from 'react'
22import { useDispatch } from 'react-redux'
33import { Action } from 'redux'
4- import { dispatchAsync } from './dispatchAsync'
4+ import { dispatchAsync , DispatchAsyncResult } from './dispatchAsync'
55
66interface ResultLoading {
77 status : 'loading'
@@ -38,6 +38,8 @@ export interface Options {
3838 timeoutInMilliseconds ?: number
3939}
4040
41+ type InnerPromiseType = Promise < boolean | DispatchAsyncResult >
42+
4143// the hook
4244export function useDispatchAsync < R = any > (
4345 actionFunction : ( ...args : any [ ] ) => Action & { payload : any } ,
@@ -51,24 +53,38 @@ export function useDispatchAsync<R = any>(
5153 const [ error , setError ] = useState < Error | undefined > ( undefined )
5254 const [ isTimeout , setIsTimeout ] = useState < boolean > ( false )
5355
56+ // 👉 race condition to get last update
57+ // https://sebastienlorber.com/handling-api-request-race-conditions-in-react
58+ // A ref to store the last issued pending request
59+ const lastPromise = useRef < InnerPromiseType > ( )
60+
5461 useEffect ( ( ) => {
5562 const actionPromise = dispatchAsync < R > ( dispatch , actionFunction ( ...deps ) )
5663
5764 const timeoutPromise = new Promise < boolean > ( ( resolve ) =>
5865 setTimeout ( ( ) => resolve ( false ) , options ?. timeoutInMilliseconds ) ,
5966 )
6067
61- Promise . race ( [ actionPromise , timeoutPromise ] )
68+ const currentPromise = Promise . race ( [ actionPromise , timeoutPromise ] )
69+
70+ lastPromise . current = currentPromise
71+
72+ currentPromise
6273 . then ( ( res ) => {
63- if ( typeof res !== 'boolean' ) {
64- res . success ? setResult ( res . result ) : setError ( res . error )
65- } else {
66- setIsTimeout ( true )
74+ // filtering last update promise
75+ if ( currentPromise === lastPromise . current ) {
76+ if ( typeof res !== 'boolean' ) {
77+ res . success ? setResult ( res . result ) : setError ( res . error )
78+ } else {
79+ setIsTimeout ( true )
80+ }
6781 }
6882 } )
6983 . catch ( ( e ) => {
70- console . error ( 'useDispatchAsync: Unexpected error' , e )
71- setError ( e )
84+ if ( currentPromise === lastPromise . current ) {
85+ console . error ( 'useDispatchAsync: Unexpected error' , e )
86+ setError ( e )
87+ }
7288 } )
7389 } , deps )
7490
0 commit comments