1
- import React , { useCallback , useEffect , useMemo , useState } from "react" ;
1
+ import React , { useCallback , useEffect , useMemo , useRef , useState } from "react" ;
2
2
import styled , { DefaultTheme , useTheme } from "styled-components" ;
3
3
4
4
import { useParams } from "react-router-dom" ;
@@ -39,6 +39,7 @@ const Container = styled.div`
39
39
flex-direction: column;
40
40
` ;
41
41
42
+ type Steps = [ _TimelineItem1 , ..._TimelineItem1 [ ] ] ;
42
43
interface IActionButton {
43
44
amount : string ;
44
45
parsedAmount : bigint ;
@@ -52,7 +53,8 @@ const StakeWithdrawButton: React.FC<IActionButton> = ({ amount, parsedAmount, ac
52
53
const theme = useTheme ( ) ;
53
54
const [ isPopupOpen , setIsPopupOpen ] = useState ( false ) ;
54
55
const [ isSuccess , setIsSuccess ] = useState ( false ) ;
55
- const [ popupStepsState , setPopupStepsState ] = useState < [ _TimelineItem1 , ..._TimelineItem1 [ ] ] > ( ) ;
56
+ const [ popupStepsState , setPopupStepsState ] = useState < Steps > ( ) ;
57
+ const controllerRef = useRef < AbortController | null > ( null ) ;
56
58
57
59
const { data : courtDetails } = useCourtDetails ( id ) ;
58
60
const { balance, jurorBalance, allowance, refetchAllowance } = usePnkData ( { courtId : id } ) ;
@@ -107,26 +109,37 @@ const StakeWithdrawButton: React.FC<IActionButton> = ({ amount, parsedAmount, ac
107
109
} ) ;
108
110
const { writeContractAsync : setStake } = useWriteKlerosCoreSetStake ( ) ;
109
111
112
+ const updatePopupState = ( signal : AbortSignal , state : Steps ) => {
113
+ if ( signal . aborted ) return ;
114
+ setPopupStepsState ( state ) ;
115
+ } ;
116
+
110
117
const handleStake = useCallback (
111
- ( config ?: typeof setStakeConfig , approvalHash ?: `0x${string } `) => {
118
+ ( signal : AbortSignal , config ?: typeof setStakeConfig , approvalHash ?: `0x${string } `) => {
119
+ if ( signal . aborted ) return ;
112
120
const isWithdraw = action === ActionType . withdraw ;
113
121
const requestData = config ?. request ?? setStakeConfig ?. request ;
114
122
const commonArgs : [ string , DefaultTheme , `0x${string } ` | undefined ] = [ amount , theme , approvalHash ] ;
115
123
116
124
if ( requestData && publicClient ) {
117
- setPopupStepsState (
125
+ updatePopupState (
126
+ signal ,
118
127
getStakeSteps ( isWithdraw ? StakeSteps . WithdrawInitiate : StakeSteps . StakeInitiate , ...commonArgs )
119
128
) ;
120
129
121
130
setStake ( requestData )
122
131
. then ( async ( hash ) => {
123
- setPopupStepsState (
132
+ if ( signal . aborted ) return ;
133
+ updatePopupState (
134
+ signal ,
124
135
getStakeSteps ( isWithdraw ? StakeSteps . WithdrawPending : StakeSteps . StakePending , ...commonArgs , hash )
125
136
) ;
126
137
await publicClient . waitForTransactionReceipt ( { hash, confirmations : 2 } ) . then ( ( res : TransactionReceipt ) => {
138
+ if ( signal . aborted ) return ;
127
139
const status = res . status === "success" ;
128
140
if ( status ) {
129
- setPopupStepsState (
141
+ updatePopupState (
142
+ signal ,
130
143
getStakeSteps (
131
144
isWithdraw ? StakeSteps . WithdrawConfirmed : StakeSteps . StakeConfirmed ,
132
145
...commonArgs ,
@@ -135,13 +148,15 @@ const StakeWithdrawButton: React.FC<IActionButton> = ({ amount, parsedAmount, ac
135
148
) ;
136
149
setIsSuccess ( true ) ;
137
150
} else
138
- setPopupStepsState (
151
+ updatePopupState (
152
+ signal ,
139
153
getStakeSteps ( isWithdraw ? StakeSteps . WithdrawFailed : StakeSteps . StakeFailed , ...commonArgs , hash )
140
154
) ;
141
155
} ) ;
142
156
} )
143
157
. catch ( ( err ) => {
144
- setPopupStepsState (
158
+ updatePopupState (
159
+ signal ,
145
160
getStakeSteps (
146
161
isWithdraw ? StakeSteps . WithdrawFailed : StakeSteps . StakeFailed ,
147
162
...commonArgs ,
@@ -157,25 +172,31 @@ const StakeWithdrawButton: React.FC<IActionButton> = ({ amount, parsedAmount, ac
157
172
158
173
const handleClick = useCallback ( ( ) => {
159
174
setIsPopupOpen ( true ) ;
175
+ controllerRef . current = new AbortController ( ) ;
176
+ const signal = controllerRef . current . signal ;
177
+
160
178
if ( isAllowance && increaseAllowanceConfig && publicClient ) {
161
179
const commonArgs : [ string , DefaultTheme ] = [ amount , theme ] ;
162
- setPopupStepsState ( getStakeSteps ( StakeSteps . ApproveInitiate , ...commonArgs ) ) ;
180
+ updatePopupState ( signal , getStakeSteps ( StakeSteps . ApproveInitiate , ...commonArgs ) ) ;
163
181
164
182
increaseAllowance ( increaseAllowanceConfig . request )
165
183
. then ( async ( hash ) => {
166
- setPopupStepsState ( getStakeSteps ( StakeSteps . ApprovePending , ...commonArgs , hash ) ) ;
184
+ if ( signal . aborted ) return ;
185
+ updatePopupState ( signal , getStakeSteps ( StakeSteps . ApprovePending , ...commonArgs , hash ) ) ;
167
186
168
187
await publicClient
169
188
. waitForTransactionReceipt ( { hash, confirmations : 2 } )
170
189
. then ( async ( res : TransactionReceipt ) => {
190
+ if ( signal . aborted ) return ;
171
191
const status = res . status === "success" ;
172
192
if ( status ) {
173
193
await refetchAllowance ( ) ;
174
194
const refetchData = await refetchWithRetry ( refetchSetStake ) ;
175
195
// check for a relatively new error with react/tanstack-query:
176
196
// https://github.com/TanStack/query/issues/8209
177
197
if ( ! refetchData ?. data )
178
- setPopupStepsState (
198
+ updatePopupState (
199
+ signal ,
179
200
getStakeSteps (
180
201
StakeSteps . ApproveFailed ,
181
202
...commonArgs ,
@@ -185,16 +206,16 @@ const StakeWithdrawButton: React.FC<IActionButton> = ({ amount, parsedAmount, ac
185
206
)
186
207
) ;
187
208
else {
188
- handleStake ( refetchData . data , hash ) ;
209
+ handleStake ( signal , refetchData . data , hash ) ;
189
210
}
190
- } else setPopupStepsState ( getStakeSteps ( StakeSteps . ApproveFailed , ...commonArgs , hash ) ) ;
211
+ } else updatePopupState ( signal , getStakeSteps ( StakeSteps . ApproveFailed , ...commonArgs , hash ) ) ;
191
212
} ) ;
192
213
} )
193
214
. catch ( ( err ) => {
194
- setPopupStepsState ( getStakeSteps ( StakeSteps . ApproveFailed , ...commonArgs , undefined , undefined , err ) ) ;
215
+ updatePopupState ( signal , getStakeSteps ( StakeSteps . ApproveFailed , ...commonArgs , undefined , undefined , err ) ) ;
195
216
} ) ;
196
217
} else {
197
- handleStake ( ) ;
218
+ handleStake ( signal ) ;
198
219
}
199
220
} , [
200
221
increaseAllowance ,
@@ -248,6 +269,9 @@ const StakeWithdrawButton: React.FC<IActionButton> = ({ amount, parsedAmount, ac
248
269
setIsSuccess ( false ) ;
249
270
setAmount ( "" ) ;
250
271
setPopupStepsState ( undefined ) ;
272
+ if ( controllerRef . current ) {
273
+ controllerRef . current . abort ( ) ;
274
+ }
251
275
} ;
252
276
253
277
return (
0 commit comments