Skip to content

Commit 7ac3ecc

Browse files
committed
defer execution to next event loop cycle
1 parent c405e22 commit 7ac3ecc

File tree

3 files changed

+28
-3
lines changed

3 files changed

+28
-3
lines changed

src/blocks/cash-app-pay/component-cash-app-pay.js

+5-1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import {
1212
createPaymentRequest,
1313
setContinuationSession,
1414
log,
15+
deferExecution,
1516
} from './utils';
1617
import { PAYMENT_METHOD_ID } from './constants';
1718

@@ -106,7 +107,7 @@ export const ComponentCashAppPay = ( props ) => {
106107
await cashAppPay.attach( `#${ buttonId }`, buttonStyles );
107108

108109
// Handle the payment response.
109-
cashAppPay.addEventListener( 'ontokenization', ( event ) => {
110+
cashAppPay.addEventListener( 'ontokenization', async ( event ) => {
110111
const { tokenResult, error } = event.detail;
111112
if ( error ) {
112113
setPaymentNonce( '' );
@@ -121,6 +122,9 @@ export const ComponentCashAppPay = ( props ) => {
121122
// Set the nonce.
122123
setPaymentNonce( nonce );
123124

125+
// See function DocBlock.
126+
await deferExecution();
127+
124128
// Place an Order.
125129
onSubmit();
126130
} else {

src/blocks/digital-wallets/content.js

+4-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import { useEffect, useState } from '@wordpress/element';
77
* Internal dependencies
88
*/
99
import { tokenize } from './utils';
10-
import { getSquareServerData } from '../square-utils/utils';
10+
import { getSquareServerData, deferExecution } from '../square-utils/utils';
1111
import {
1212
useSquare,
1313
usePaymentRequest,
@@ -76,6 +76,9 @@ const Content = ( {
7676
onClose();
7777
} else {
7878
setTokenResult( __tokenResult );
79+
80+
// See function DocBlock.
81+
await deferExecution();
7982
onSubmit();
8083
}
8184
} )();

src/blocks/square-utils/utils.js

+19-1
Original file line numberDiff line numberDiff line change
@@ -134,4 +134,22 @@ const log = ( data, type = 'notice' ) => {
134134
}
135135
};
136136

137-
export { getSquareServerData, handleErrors, log, logData };
137+
/**
138+
* Defers execution to the next event loop cycle to ensure state updates are committed.
139+
*
140+
* React 18 (introduced in WooCommerce 9.8) batches state updates inside event handlers,
141+
* which can cause issues where state is not updated in time before dependent logic runs.
142+
*
143+
* This utility function forces JavaScript to defer execution to the next microtask,
144+
* ensuring that any state updates are fully committed before continuing execution.
145+
*
146+
* Introduced specifically to handle WooCommerce 9.8 and above, where React 18's
147+
* concurrent rendering changes impact payment tokenization timing.
148+
*
149+
* @see https://github.com/woocommerce/woocommerce/pull/52473 for more details.
150+
*
151+
* @returns {Promise<void>} A promise that resolves in the next event loop cycle.
152+
*/
153+
const deferExecution = () => new Promise( ( resolve ) => setTimeout( resolve, 0 ) );
154+
155+
export { getSquareServerData, handleErrors, log, logData, deferExecution };

0 commit comments

Comments
 (0)