Skip to content

Commit 0e40a91

Browse files
committed
fix: stabilize React hooks to prevent excessive re-renders
- Wrap useButtonStateManager return object in useMemo - Memoize useCardholderName, useMoneiCardInput, useFormErrors returns - Add useCallback to initMoneiBizum, updateBizumAmount in Bizum component - Add useCallback to initMoneiPayPal, updatePaypalAmount in PayPal component - Fix all useEffect dependency arrays per react-hooks/exhaustive-deps warnings - Hoist function definitions before useEffect hooks to fix initialization order - Rename initMoneiCard to initMoneiBizum for clarity - Add missing useCallback import in PayPal component - Resolves 9 ESLint hooks warnings in Bizum and PayPal components
1 parent c8bf857 commit 0e40a91

File tree

4 files changed

+110
-62
lines changed

4 files changed

+110
-62
lines changed

assets/js/helpers/monei-card-input-hooks.js

Lines changed: 52 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -46,20 +46,25 @@ export const useCardholderName = ( config = {} ) => {
4646
validate();
4747
}, [ validate ] );
4848

49-
return {
50-
value,
51-
error,
52-
touched,
53-
isValid: ! error && touched,
54-
handleChange,
55-
handleBlur,
56-
validate,
57-
reset: () => {
58-
setValue( '' );
59-
setError( '' );
60-
setTouched( false );
61-
},
62-
};
49+
const reset = useCallback( () => {
50+
setValue( '' );
51+
setError( '' );
52+
setTouched( false );
53+
}, [] );
54+
55+
return useMemo(
56+
() => ( {
57+
value,
58+
error,
59+
touched,
60+
isValid: ! error && touched,
61+
handleChange,
62+
handleBlur,
63+
validate,
64+
reset,
65+
} ),
66+
[ value, error, touched, handleChange, handleBlur, validate, reset ]
67+
);
6368
};
6469

6570
/**
@@ -225,16 +230,28 @@ export const useMoneiCardInput = ( config ) => {
225230
};
226231
}, [] );
227232

228-
return {
229-
isReady,
230-
error,
231-
isValid,
232-
token,
233-
isCreatingToken,
234-
containerRef,
235-
createToken,
236-
reset,
237-
};
233+
return useMemo(
234+
() => ( {
235+
isReady,
236+
error,
237+
isValid,
238+
token,
239+
isCreatingToken,
240+
containerRef,
241+
createToken,
242+
reset,
243+
} ),
244+
[
245+
isReady,
246+
error,
247+
isValid,
248+
token,
249+
isCreatingToken,
250+
containerRef,
251+
createToken,
252+
reset,
253+
]
254+
);
238255
};
239256

240257
/**
@@ -274,12 +291,15 @@ export const useFormErrors = () => {
274291
[ errors ]
275292
);
276293

277-
return {
278-
errors,
279-
setError,
280-
clearError,
281-
clearAllErrors,
282-
hasErrors,
283-
getError,
284-
};
294+
return useMemo(
295+
() => ( {
296+
errors,
297+
setError,
298+
clearError,
299+
clearAllErrors,
300+
hasErrors,
301+
getError,
302+
} ),
303+
[ errors, setError, clearError, clearAllErrors, hasErrors, getError ]
304+
);
285305
};

assets/js/helpers/monei-shared-utils.js

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ export const getPlaceOrderButton = () => {
1717
* @return {Object}
1818
*/
1919
export const useButtonStateManager = ( props ) => {
20-
const { useEffect, useState, useRef } = wp.element;
20+
const { useEffect, useState, useRef, useCallback, useMemo } = wp.element;
2121
const [ buttonReady, setButtonReady ] = useState( false );
2222
const tokenRef = useRef( null );
2323

@@ -44,7 +44,7 @@ export const useButtonStateManager = ( props ) => {
4444
};
4545
}, [ props.isActive, buttonReady ] );
4646

47-
const enableCheckout = ( token ) => {
47+
const enableCheckout = useCallback( ( token ) => {
4848
tokenRef.current = token;
4949
setButtonReady( true );
5050

@@ -55,9 +55,9 @@ export const useButtonStateManager = ( props ) => {
5555
button.disabled = false;
5656
button.click();
5757
}
58-
};
58+
}, [] );
5959

60-
const getPaymentData = () => {
60+
const getPaymentData = useCallback( () => {
6161
if ( ! tokenRef.current ) {
6262
return {
6363
type: props.emitResponse.responseTypes.ERROR,
@@ -73,11 +73,18 @@ export const useButtonStateManager = ( props ) => {
7373
},
7474
},
7575
};
76-
};
76+
}, [
77+
props.emitResponse.responseTypes,
78+
props.errorMessage,
79+
props.tokenFieldName,
80+
] );
7781

78-
return {
79-
enableCheckout,
80-
getPaymentData,
81-
tokenRef,
82-
};
82+
return useMemo(
83+
() => ( {
84+
enableCheckout,
85+
getPaymentData,
86+
tokenRef,
87+
} ),
88+
[ enableCheckout, getPaymentData ]
89+
);
8390
};

assets/js/monei-block-checkout-bizum.js

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
( function () {
22
const { registerPaymentMethod } = wc.wcBlocksRegistry;
33
const { __ } = wp.i18n;
4-
const { useEffect, useRef, useState, createPortal } = wp.element;
4+
const { useEffect, useRef, useState, createPortal, useCallback } =
5+
wp.element;
56
const { useSelect } = wp.data;
67
const bizumData = wc.wcSettings.getSetting( 'monei_bizum_data' );
78

@@ -53,7 +54,7 @@
5354
placeOrderButton.disabled = false;
5455
}
5556
};
56-
}, [ activePaymentMethod ] );
57+
}, [ activePaymentMethod, isRedirectFlow ] );
5758

5859
useEffect( () => {
5960
// Don't initialize Bizum component if using redirect flow
@@ -72,7 +73,7 @@
7273
} else if ( ! monei || ! monei.Bizum ) {
7374
console.error( 'MONEI SDK is not available' );
7475
}
75-
}, [] ); // Only initialize once on mount
76+
}, [ initMoneiCard, isRedirectFlow ] );
7677

7778
useEffect( () => {
7879
// Don't update amount if using redirect flow
@@ -88,12 +89,12 @@
8889
) {
8990
updateBizumAmount();
9091
}
91-
}, [ cartTotals ] ); // Update amount when cart totals change
92+
}, [ cartTotals, updateBizumAmount, isRedirectFlow ] );
9293

9394
/**
9495
* Initialize MONEI Bizum instance once.
9596
*/
96-
const initMoneiCard = () => {
97+
const initMoneiCard = useCallback( () => {
9798
const currentTotal = cartTotals?.total_price
9899
? parseInt( cartTotals.total_price )
99100
: parseInt( bizumData.total * 100 );
@@ -153,12 +154,12 @@
153154
setTimeout( () => {
154155
setIsLoading( false );
155156
}, 1000 );
156-
};
157+
}, [ cartTotals ] );
157158

158159
/**
159160
* Update the amount in the existing Bizum instance.
160161
*/
161-
const updateBizumAmount = () => {
162+
const updateBizumAmount = useCallback( () => {
162163
const currentTotal = cartTotals?.total_price
163164
? parseInt( cartTotals.total_price )
164165
: parseInt( bizumData.total * 100 );
@@ -234,7 +235,7 @@
234235
setIsLoading( false );
235236
}, 100 );
236237
}
237-
};
238+
}, [ cartTotals ] );
238239

239240
// Hook into the payment setup
240241
useEffect( () => {
@@ -276,7 +277,12 @@
276277
return () => {
277278
unsubscribePaymentSetup();
278279
};
279-
}, [ onPaymentSetup ] );
280+
}, [
281+
onPaymentSetup,
282+
isRedirectFlow,
283+
responseTypes.SUCCESS,
284+
responseTypes.ERROR,
285+
] );
280286

281287
useEffect( () => {
282288
const unsubscribe = onCheckoutSuccess(
@@ -351,7 +357,11 @@
351357
return () => {
352358
unsubscribe();
353359
};
354-
}, [ onCheckoutSuccess ] );
360+
}, [
361+
onCheckoutSuccess,
362+
responseTypes,
363+
props.emitResponse.noticeContexts,
364+
] );
355365

356366
// Cleanup on unmount
357367
useEffect( () => {

assets/js/monei-block-checkout-paypal.js

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
( function () {
22
const { registerPaymentMethod } = wc.wcBlocksRegistry;
33
const { __ } = wp.i18n;
4-
const { useEffect, useState, createPortal, useRef } = wp.element;
4+
const { useEffect, useState, createPortal, useRef, useCallback } =
5+
wp.element;
56
const { useSelect } = wp.data;
67
const paypalData = wc.wcSettings.getSetting( 'monei_paypal_data' );
78

@@ -57,12 +58,12 @@
5758
placeOrderButton.disabled = false;
5859
}
5960
};
60-
}, [ activePaymentMethod ] );
61+
}, [ activePaymentMethod, isRedirectFlow ] );
6162

6263
/**
6364
* Initialize MONEI PayPal component and handle token creation.
6465
*/
65-
const initMoneiPayPal = () => {
66+
const initMoneiPayPal = useCallback( () => {
6667
// eslint-disable-next-line no-undef
6768
if ( typeof monei === 'undefined' || ! monei.PayPal ) {
6869
console.error( 'MONEI SDK is not available' );
@@ -140,12 +141,12 @@
140141
setTimeout( () => {
141142
setIsLoading( false );
142143
}, 1000 );
143-
};
144+
}, [ cartTotals ] );
144145

145146
/**
146147
* Update the amount in the existing PayPal instance
147148
*/
148-
const updatePaypalAmount = () => {
149+
const updatePaypalAmount = useCallback( () => {
149150
const currentTotal = cartTotals?.total_price
150151
? parseInt( cartTotals.total_price )
151152
: Math.round( paypalData.total * 100 );
@@ -225,7 +226,7 @@
225226
setIsLoading( false );
226227
}, 1000 );
227228
}
228-
};
229+
}, [ cartTotals ] );
229230

230231
// Initialize on mount
231232
useEffect( () => {
@@ -245,7 +246,7 @@
245246
} else if ( ! monei || ! monei.PayPal ) {
246247
console.error( 'MONEI SDK is not available' );
247248
}
248-
}, [] );
249+
}, [ initMoneiPayPal, isRedirectFlow ] );
249250

250251
// Update amount when cart totals change
251252
useEffect( () => {
@@ -256,7 +257,7 @@
256257
) {
257258
updatePaypalAmount();
258259
}
259-
}, [ cartTotals ] );
260+
}, [ cartTotals, updatePaypalAmount ] );
260261

261262
// Cleanup on unmount
262263
useEffect( () => {
@@ -311,7 +312,12 @@
311312
return () => {
312313
unsubscribePaymentSetup();
313314
};
314-
}, [ onPaymentSetup ] );
315+
}, [
316+
onPaymentSetup,
317+
isRedirectFlow,
318+
responseTypes.SUCCESS,
319+
responseTypes.ERROR,
320+
] );
315321

316322
useEffect( () => {
317323
const unsubscribe = onCheckoutSuccess(
@@ -386,7 +392,12 @@
386392
return () => {
387393
unsubscribe();
388394
};
389-
}, [ onCheckoutSuccess ] );
395+
}, [
396+
onCheckoutSuccess,
397+
props.emitResponse.noticeContexts.PAYMENTS,
398+
responseTypes.SUCCESS,
399+
responseTypes.ERROR,
400+
] );
390401

391402
// In redirect mode, show description instead of PayPal button
392403
if ( isRedirectFlow ) {

0 commit comments

Comments
 (0)