woocommerce / woocommerce-gateway-stripe

The official Stripe Payment Gateway for WooCommerce
https://wordpress.org/plugins/woocommerce-gateway-stripe/
229 stars 197 forks source link

Checkout fields fail to render in the WordPress customizer preview after a refresh (when a customizer setting is updated) #3225

Open danielshawellis opened 1 week ago

danielshawellis commented 1 week ago

Describe the bug Whenever a setting with 'transport' => 'refresh' is changed in the WordPress customizer, WordPress will reload the entire preview iframe. When this happens, the upe_blocks.js script throws the following error:

ReferenceError: wc_stripe_upe_params is not defined
    at A (upe_blocks.js?ver=9721965e3d4217790b0c028bc16f3960:1:105128)
    at b (upe_blocks.js?ver=9721965e3d4217790b0c028bc16f3960:1:110654)
    at v (upe_blocks.js?ver=9721965e3d4217790b0c028bc16f3960:1:236091)
    at wt (react-dom.min.js?ver=18.2.0:10:47637)
    at js (react-dom.min.js?ver=18.2.0:10:120584)
    at wl (react-dom.min.js?ver=18.2.0:10:88659)
    at bl (react-dom.min.js?ver=18.2.0:10:88587)
    at yl (react-dom.min.js?ver=18.2.0:10:88450)
    at fl (react-dom.min.js?ver=18.2.0:10:85607)
    at Nn (react-dom.min.js?ver=18.2.0:10:32474)

When this happens, the checkout fields will fail to render in the preview iframe:

Screenshot from 2024-06-25 15-34-23

Here's a video of the issue for clarity:

full-issue-demonstration.webm

To Reproduce Steps to reproduce the behavior:

  1. Set up WooCommerce, the WooCommerce Stripe Gateway, and a very simple plugin to add a customizer setting with 'transport' => 'refresh'. Here's the plugin that I used for testing:
    
    <?php
    /*
    Plugin Name: Simple Customizer Checkbox
    */

if ( ! defined( 'ABSPATH' ) ) { exit; // Exit if accessed directly. }

function simple_customizer_checkbox_register( $wp_customize ) { // Add a section to the Customizer $wp_customize->add_section( 'simple_checkbox_section', array( 'title' => __( 'Simple Checkbox Section', 'simple_customizer_checkbox' ), 'priority' => 30, ) );

// Add a setting for the checkbox
$wp_customize->add_setting( 'simple_checkbox_setting', array(
    'default'   => false,
    'transport' => 'refresh', // Ensure that changes to the setting trigger a reload of the whole preview frame: https://developer.wordpress.org/reference/classes/WP_Customize_Setting/__construct/
) );

// Add the checkbox control
$wp_customize->add_control( 'simple_checkbox_control', array(
    'label'    => __( 'Enable Simple Checkbox', 'simple_customizer_checkbox' ),
    'section'  => 'simple_checkbox_section',
    'settings' => 'simple_checkbox_setting',
    'type'     => 'checkbox',
) );

}

add_action( 'customize_register', 'simple_customizer_checkbox_register' );



2. Navigate to the site's checkout page and open the WordPress customizer
3. Update a customizer setting with `'transport' => 'refresh'` (i.e. check the "Enable Simple Checkbox" setting if using the above "Simple Customizer Checkbox" plugin  
4. Notice that when the customizer preview iframe refreshes, the checkout fields fail to render and the `wc_stripe_upe_params is not defined` error is visible in the JS console
5. If the issue doesn't occur immediately, try spamming changes to the setting and/or [throttling the CPU on your browser](https://umaar.com/dev-tips/88-cpu-throttling/).
5. Interestingly, notice that when the customizer iframe is targeted in the JS console, `window.wc_stripe_upe_params` is set even after the JS error is thrown. See the video for clarification. To me, this indicates a probable race condition.

**Expected behavior**
The checkout fields should render correctly in the customizer preview iframe after the iframe is refreshed.

**Screenshots**
See the screenshot and video in the bug description.

**Environment (please complete the following information):**
 - WordPress Version:   6.5.5
 - WooCommerce Version: 9.0.2
 - Stripe Plugin Version: 8.4.0
 - Browsers: Chromium Version 126.0.6478.114 (Official Build) (64-bit)
 - Other plugins installed: WooCommerce, WooCommerce Stripe Gateway, and the "Simple Customizer Checkbox" plugin (source code above in the description)

**Additional context**
This problem is sometimes difficult to produce and it doesn't occur on every refresh. I believe that there must be a race condition causing it. If you aren't immediately able to reproduce it, try spamming changes to the relevant customizer setting until you see issues. It may also be helpful to throttle the CPU in Chrome developer tools: https://umaar.com/dev-tips/88-cpu-throttling/ Per my tests, the issue seems to happen more reliably when the CPU is throttled.