Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitdd7adda

Browse files
refactor: consolidate useRetry state with useReducer
Convert useRetry hook from multiple useState calls to a single useReducerfor cleaner state management. This improves code clarity and makes statetransitions more predictable.Changes:- Replace 5 useState calls with single useReducer- Add RetryState interface and RetryAction union type- Implement retryReducer function for all state transitions- Update all state access to use state object- Replace setState calls with dispatch calls throughoutCo-authored-by: BrunoQuaresma <3165839+BrunoQuaresma@users.noreply.github.com>
1 parentd398265 commitdd7adda

File tree

1 file changed

+104
-40
lines changed

1 file changed

+104
-40
lines changed

‎site/src/hooks/useRetry.ts‎

Lines changed: 104 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import{useCallback,useEffect,useRef,useState}from"react";
1+
import{useCallback,useEffect,useReducer,useRef}from"react";
22
import{useEffectEvent}from"./hookPolyfills";
33

44
interfaceUseRetryOptions{
@@ -55,18 +55,89 @@ interface UseRetryReturn {
5555
stopRetrying:()=>void;
5656
}
5757

58+
interfaceRetryState{
59+
isRetrying:boolean;
60+
currentDelay:number|null;
61+
attemptCount:number;
62+
timeUntilNextRetry:number|null;
63+
isManualRetry:boolean;
64+
}
65+
66+
typeRetryAction=
67+
|{type:"START_RETRY"}
68+
|{type:"RETRY_SUCCESS"}
69+
|{type:"RETRY_FAILURE"}
70+
|{type:"SCHEDULE_RETRY";delay:number}
71+
|{type:"UPDATE_COUNTDOWN";timeRemaining:number}
72+
|{type:"CANCEL_RETRY"}
73+
|{type:"RESET"}
74+
|{type:"SET_MANUAL_RETRY";isManual:boolean};
75+
76+
constinitialState:RetryState={
77+
isRetrying:false,
78+
currentDelay:null,
79+
attemptCount:0,
80+
timeUntilNextRetry:null,
81+
isManualRetry:false,
82+
};
83+
84+
functionretryReducer(state:RetryState,action:RetryAction):RetryState{
85+
switch(action.type){
86+
case"START_RETRY":
87+
return{
88+
...state,
89+
isRetrying:true,
90+
currentDelay:null,
91+
timeUntilNextRetry:null,
92+
attemptCount:state.attemptCount+1,
93+
};
94+
case"RETRY_SUCCESS":
95+
return{
96+
...initialState,
97+
};
98+
case"RETRY_FAILURE":
99+
return{
100+
...state,
101+
isRetrying:false,
102+
isManualRetry:false,
103+
};
104+
case"SCHEDULE_RETRY":
105+
return{
106+
...state,
107+
currentDelay:action.delay,
108+
timeUntilNextRetry:action.delay,
109+
};
110+
case"UPDATE_COUNTDOWN":
111+
return{
112+
...state,
113+
timeUntilNextRetry:action.timeRemaining,
114+
};
115+
case"CANCEL_RETRY":
116+
return{
117+
...state,
118+
currentDelay:null,
119+
timeUntilNextRetry:null,
120+
};
121+
case"RESET":
122+
return{
123+
...initialState,
124+
};
125+
case"SET_MANUAL_RETRY":
126+
return{
127+
...state,
128+
isManualRetry:action.isManual,
129+
};
130+
default:
131+
returnstate;
132+
}
133+
}
134+
58135
/**
59136
* Hook for handling exponential backoff retry logic
60137
*/
61138
exportfunctionuseRetry(options:UseRetryOptions):UseRetryReturn{
62139
const{ onRetry, maxAttempts, initialDelay, maxDelay, multiplier}=options;
63-
const[isRetrying,setIsRetrying]=useState(false);
64-
const[currentDelay,setCurrentDelay]=useState<number|null>(null);
65-
const[attemptCount,setAttemptCount]=useState(0);
66-
const[timeUntilNextRetry,setTimeUntilNextRetry]=useState<number|null>(
67-
null,
68-
);
69-
const[isManualRetry,setIsManualRetry]=useState(false);
140+
const[state,dispatch]=useReducer(retryReducer,initialState);
70141

71142
consttimeoutRef=useRef<number|null>(null);
72143
constcountdownRef=useRef<number|null>(null);
@@ -95,23 +166,16 @@ export function useRetry(options: UseRetryOptions): UseRetryReturn {
95166
);
96167

97168
constperformRetry=useCallback(async()=>{
98-
setIsRetrying(true);
99-
setTimeUntilNextRetry(null);
100-
setCurrentDelay(null);
169+
dispatch({type:"START_RETRY"});
101170
clearTimers();
102-
// Increment attempt count when starting the retry
103-
setAttemptCount((prev)=>prev+1);
104171

105172
try{
106173
awaitonRetryEvent();
107174
// If retry succeeds, reset everything
108-
setAttemptCount(0);
109-
setIsRetrying(false);
110-
setIsManualRetry(false);
175+
dispatch({type:"RETRY_SUCCESS"});
111176
}catch(error){
112-
// If retry fails, just update state (attemptCount already incremented)
113-
setIsRetrying(false);
114-
setIsManualRetry(false);
177+
// If retry fails, just update state
178+
dispatch({type:"RETRY_FAILURE"});
115179
}
116180
},[onRetryEvent,clearTimers]);
117181

@@ -123,16 +187,15 @@ export function useRetry(options: UseRetryOptions): UseRetryReturn {
123187

124188
// Calculate delay based on attempt - 1 (so first retry gets initialDelay)
125189
constdelay=calculateDelay(Math.max(0,attempt-1));
126-
setCurrentDelay(delay);
127-
setTimeUntilNextRetry(delay);
190+
dispatch({type:"SCHEDULE_RETRY", delay});
128191
startTimeRef.current=Date.now();
129192

130193
// Start countdown timer
131194
countdownRef.current=window.setInterval(()=>{
132195
if(startTimeRef.current){
133196
constelapsed=Date.now()-startTimeRef.current;
134197
constremaining=Math.max(0,delay-elapsed);
135-
setTimeUntilNextRetry(remaining);
198+
dispatch({type:"UPDATE_COUNTDOWN",timeRemaining:remaining});
136199

137200
if(remaining<=0){
138201
if(countdownRef.current){
@@ -154,20 +217,25 @@ export function useRetry(options: UseRetryOptions): UseRetryReturn {
154217
// Effect to schedule next retry after a failed attempt
155218
useEffect(()=>{
156219
if(
157-
!isRetrying&&
158-
!isManualRetry&&
159-
attemptCount>0&&
160-
attemptCount<maxAttempts
220+
!state.isRetrying&&
221+
!state.isManualRetry&&
222+
state.attemptCount>0&&
223+
state.attemptCount<maxAttempts
161224
){
162-
scheduleNextRetry(attemptCount);
225+
scheduleNextRetry(state.attemptCount);
163226
}
164-
},[attemptCount,isRetrying,isManualRetry,maxAttempts,scheduleNextRetry]);
227+
},[
228+
state.attemptCount,
229+
state.isRetrying,
230+
state.isManualRetry,
231+
maxAttempts,
232+
scheduleNextRetry,
233+
]);
165234

166235
constretry=useCallback(()=>{
167-
setIsManualRetry(true);
236+
dispatch({type:"SET_MANUAL_RETRY",isManual:true});
168237
clearTimers();
169-
setTimeUntilNextRetry(null);
170-
setCurrentDelay(null);
238+
dispatch({type:"CANCEL_RETRY"});
171239
performRetry();
172240
},[clearTimers,performRetry]);
173241

@@ -178,11 +246,7 @@ export function useRetry(options: UseRetryOptions): UseRetryReturn {
178246

179247
conststopRetrying=useCallback(()=>{
180248
clearTimers();
181-
setIsRetrying(false);
182-
setCurrentDelay(null);
183-
setAttemptCount(0);
184-
setTimeUntilNextRetry(null);
185-
setIsManualRetry(false);
249+
dispatch({type:"RESET"});
186250
},[clearTimers]);
187251

188252
// Cleanup on unmount
@@ -194,10 +258,10 @@ export function useRetry(options: UseRetryOptions): UseRetryReturn {
194258

195259
return{
196260
retry,
197-
isRetrying,
198-
currentDelay,
199-
attemptCount,
200-
timeUntilNextRetry,
261+
isRetrying:state.isRetrying,
262+
currentDelay:state.currentDelay,
263+
attemptCount:state.attemptCount,
264+
timeUntilNextRetry:state.timeUntilNextRetry,
201265
startRetrying,
202266
stopRetrying,
203267
};

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp