Skip to content

fix: replace infinite spinner with static placeholder in Pay Later block editor preview (5801)#4302

Open
Narek13 wants to merge 7 commits intodev/developfrom
dev/PCP-5801-replace-infinite-spinner-with-static-placeholder-in-pay-later-block-editor-preview
Open

fix: replace infinite spinner with static placeholder in Pay Later block editor preview (5801)#4302
Narek13 wants to merge 7 commits intodev/developfrom
dev/PCP-5801-replace-infinite-spinner-with-static-placeholder-in-pay-later-block-editor-preview

Conversation

@Narek13
Copy link
Copy Markdown
Collaborator

@Narek13 Narek13 commented Apr 27, 2026

Problem

When editing the checkout/cart page in the block editor, the Pay Later messaging block could display an infinite spinner that never resolves. This happens when eligibility requirements (merchant status, geolocation, store configuration) cannot be determined in the editor context, causing the PayPal SDK to silently skip rendering without calling onRender.

Solution

Added a 5-second timeout mechanism to all three Pay Later block editor components. If the messaging preview has not loaded within 5 seconds, the spinner is replaced with a static placeholder:

"Pay Later messaging preview unavailable in editor. Messaging will display on the frontend when eligibility conditions are met."

PayPal Pay Later messaging block (any page) WooCommerce Checkout/Cart block
Screenshot 2026-04-27 at 16 24 06 Screenshot 2026-04-27 at 16 24 21

If the preview loads successfully within 5 seconds, behavior is unchanged.

Changes

  • CheckoutPayLaterMessagesBlock/edit.js — timeout + placeholder
  • CartPayLaterMessagesBlock/edit.js — timeout + placeholder
  • ppcp-paylater-block/resources/js/edit.js — timeout + placeholder
  • tests/js/jest.config.json — added @ppcp-paylater-block Jest alias
  • Added unit tests for all three blocks (18 tests total)

Testing

Switch the WooCommerce store currency to one where Pay Later messaging is not supported — the placeholder should appear after 5 seconds.

Notes

  • Frontend rendering is unaffected
  • Block controls remain accessible during and after the timeout

Narek13 added 7 commits April 27, 2026 16:06
…review

Replaces the infinite spinner with a static message after 5 seconds when the Pay Later messaging preview cannot be resolved in the editor context.
Replaces the infinite spinner with a static message after 5 seconds when the Pay Later messaging preview cannot be resolved in the editor context.
…eview

Replaces the infinite spinner with a static message after 5 seconds when the Pay Later messaging preview cannot be resolved in the editor context.
Required to resolve the useScriptParams hook import when running unit tests for the paylater WC blocks.
Covers spinner display, 5s placeholder fallback, successful render, and warning states.
Covers spinner display, 5s placeholder fallback, successful render, and warning states.
Covers spinner display, 5s placeholder fallback, successful render, and warning states.
@github-actions
Copy link
Copy Markdown

Test using WordPress Playground

The changes in this pull request can be previewed and tested using a WordPress Playground instance.
WordPress Playground is an experimental project that creates a full WordPress instance entirely within the browser.

🔗 Test this pull request with WordPress Playground

What's included:

  • ✅ WordPress (latest)
  • ✅ WooCommerce (latest)
  • ✅ PayPal Payments plugin v4.0.2-pr4302-24995169137-ge531895 (built from this PR)

Login credentials:

  • Username: admin
  • Password: password

Plugin Details:

  • Version: 4.0.2-pr4302-24995169137-ge531895
  • Commit: 12125ca
  • Artifact: woocommerce-paypal-payments-4.0.2-pr4302-24995169137-ge531895

💡 The demo environment resets each time you refresh. Perfect for testing!

🔄 This link updates automatically with each new commit to the PR.

⚠️ This URL is valid for 30 days from when this comment was last updated.


🤖 Auto-generated for commit 12125ca • Last updated: 2026-04-27T12:46:34.929Z

@InpsydeNiklas InpsydeNiklas linked an issue Apr 27, 2026 that may be closed by this pull request
Copy link
Copy Markdown
Collaborator

@Dinamiko Dinamiko left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR looks good, happy to see that you added tests :)

Maybe consider reducing code duplication by extracting logic to a custom hook and a component:

Custom hook

New file: modules/ppcp-paylater-block/resources/js/hooks/use-preview-timeout.js

  import { useState, useEffect } from '@wordpress/element';            
                                                                                                                                                                                                                       
  export const PREVIEW_TIMEOUT_MS = 5000;                                                                                                                                                                              
   
  /**                                                                                                                                                                                                                  
   * Flips to `true` once `timeoutMs` has elapsed without `loaded` becoming truthy.
   * Returns `false` if the preview loaded in time. Cleans up on unmount or when                                                                                                                                       
   * `loaded` flips, so no setState-on-unmounted warnings.                                                                                                                                                             
   */                                                                                                                                                                                                                  
  export function usePreviewTimeout( loaded, timeoutMs = PREVIEW_TIMEOUT_MS ) {                                                                                                                                        
        const [ timedOut, setTimedOut ] = useState( false );                                                                                                                                                           
                                                                       
        useEffect( () => {                                                                                                                                                                                             
                if ( loaded ) {                                        
                        return;
                }
                const timer = setTimeout( () => setTimedOut( true ), timeoutMs );                                                                                                                                      
                return () => clearTimeout( timer );
        }, [ loaded, timeoutMs ] );                                                                                                                                                                                    
                                                                                                                                                                                                                       
        return timedOut;
  }  

Shared placeholder component

New file: modules/ppcp-paylater-block/resources/js/components/preview-placeholder.js

  import { __ } from '@wordpress/i18n';                                                                                                                                                                                
  import { Spinner } from '@wordpress/components';                     
                                                                                                                                                                                                            
  export function PreviewPlaceholder( { timedOut } ) {                                                                                                                                                                 
        if ( ! timedOut ) {                                            
                return <Spinner />;
        }
        return (
                <p className="ppcp-paylater-preview-placeholder">
                        { __(                                                                                                                                                                                          
                                'Pay Later messaging preview unavailable in editor. Messaging will display on the frontend when eligibility conditions are met.',
                                'woocommerce-paypal-payments'                                                                                                                                                          
                        ) }                                            
                </p>                                                                                                                                                                                                   
        );                                                             
  }       

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Spinning block in checkout editor page (5801)

2 participants