-
Notifications
You must be signed in to change notification settings - Fork 524
Expand file tree
/
Copy pathuse-query-route-refresh.ts
More file actions
87 lines (81 loc) · 3.46 KB
/
use-query-route-refresh.ts
File metadata and controls
87 lines (81 loc) · 3.46 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
import { SwapAmountConfig } from "@keplr-wallet/hooks-internal";
import { ObservableQueryRouteInnerV2 } from "@keplr-wallet/stores-internal";
import { useEffect, useRef } from "react";
export function useQueryRouteRefresh(
queryRoute: ObservableQueryRouteInnerV2 | undefined,
isSwapExecuting: boolean,
isButtonHolding: boolean,
isApprovalResetRequired?: boolean
) {
const isPaused =
isSwapExecuting || isButtonHolding || !!isApprovalResetRequired;
const prevIsSwapLoadingRef = useRef(isSwapExecuting);
const prevIsButtonHoldingRef = useRef(isButtonHolding);
// 컴포넌트 마운트 시 캐시된 route가 만료 임박 상태면 즉시 refresh
// 페이지를 떠났다가 돌아왔을 때 오래된 캐시로 인한 quote expired 오류 방지
useEffect(() => {
if (
queryRoute &&
!queryRoute.isFetching &&
!isPaused &&
queryRoute.response?.timestamp
) {
const diff = Date.now() - queryRoute.response.timestamp;
// 만료 임계값(25초)의 절반(10초) 이상 지났으면 즉시 refresh
if (diff > SwapAmountConfig.QueryRouteRefreshInterval / 2) {
queryRoute.fetch();
}
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [queryRoute]); // queryRoute reference 변경 시에만 실행 (마운트 또는 파라미터 변경)
// 사용자가 스왑 버튼을 홀딩하다가 중간에 손을 떼었을 때 (isButtonHolding이 true에서 false로 변경되었을 때)
// 또는 tx 처리 중에 오류가 발생했을 때 (isSwapExecuting이 true에서 false로 변경되었을 때)
// quote expired가 발생할 수 있으므로 3초 후 쿼리 리프레시
useEffect(() => {
const prevIsSwapLoading = prevIsSwapLoadingRef.current;
const prevIsButtonHolding = prevIsButtonHoldingRef.current;
const currentIsSwapLoading = isSwapExecuting;
const currentIsButtonHolding = isButtonHolding;
if (
queryRoute &&
!queryRoute.isFetching &&
((prevIsSwapLoading && !currentIsSwapLoading) ||
(prevIsButtonHolding && !currentIsButtonHolding))
) {
const timeoutId = setTimeout(() => {
if (queryRoute && !queryRoute.isFetching && !isPaused) {
queryRoute.fetch();
}
}, 3000);
return () => {
clearTimeout(timeoutId);
};
}
prevIsSwapLoadingRef.current = currentIsSwapLoading;
prevIsButtonHoldingRef.current = currentIsButtonHolding;
}, [
queryRoute,
queryRoute?.isFetching,
isSwapExecuting,
isButtonHolding,
isPaused,
]);
// QueryRouteRefreshInterval 마다 route query 자동 refresh
useEffect(() => {
if (queryRoute && !queryRoute.isFetching && !isPaused) {
const timeoutId = setTimeout(() => {
if (!queryRoute.isFetching && !isPaused) {
queryRoute.fetch();
}
}, SwapAmountConfig.QueryRouteRefreshInterval);
return () => {
clearTimeout(timeoutId);
};
}
// eslint가 자동으로 추천해주는 deps를 쓰면 안된다.
// queryRoute는 amountConfig에서 필요할때마다 reference가 바뀌므로 deps에 넣는다.
// queryRoute.isFetching는 현재 fetch중인지 아닌지를 알려주는 값이므로 deps에 꼭 넣어야한다.
// queryRoute는 input이 같으면 reference가 같으므로 eslint에서 추천하는대로 queryRoute만 deps에 넣으면
// queryRoute.isFetching이 무시되기 때문에 수동으로 넣어줌
}, [queryRoute, queryRoute?.isFetching, isPaused]);
}