Skip to content

Commit cfa23b2

Browse files
committed
feat: 🎸 use race condition take latest promise
✅ Closes: #1
1 parent e2ca048 commit cfa23b2

File tree

1 file changed

+25
-9
lines changed

1 file changed

+25
-9
lines changed

‎src/useDispatchAsync.ts‎

Lines changed: 25 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
import { useEffect, useMemo, useState } from 'react'
1+
import { useEffect, useMemo, useRef, useState } from 'react'
22
import { useDispatch } from 'react-redux'
33
import { Action } from 'redux'
4-
import { dispatchAsync } from './dispatchAsync'
4+
import { dispatchAsync, DispatchAsyncResult } from './dispatchAsync'
55

66
interface 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
4244
export 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

Comments
 (0)