I get the warning ppxo_button_pre_template_click and the button is not responsive when I click it , for a few seconds after the button appears
[x] Screenshots or videos that show the issue

[x] Your code
CREATE_PAYMENT_URL = 'http://localhost:3000/paypal/create_payment';
EXECUTE_PAYMENT_URL = 'http://localhost:3000/paypal/execute_payment';
paypal.Button.render({
locale: 'en_US',
env: 'sandbox',
payment: function() {
return new paypal.Promise(function(resolve, reject) {
$('.paypal-overlay').fadeIn();
$.post(CREATE_PAYMENT_URL)
.done(function(data) { resolve(data.paymentID); })
.fail(function(err) { $('.paypal-overlay').fadeOut(); });
});
},
onAuthorize: function(data) {
console.log('The payment was authorized!');
console.log('Payment ID = ', data.paymentID);
console.log('PayerID = ', data.payerID);
$.post(EXECUTE_PAYMENT_URL, { paymentID: data.paymentID, payerID: data.payerID })
.done(function(data) {
window.location = '/payments/summary'
})
.fail(function(err) {
window.location = '/payments/cancelled'
});
},
onCancel: function(data) {
window.location = '/payments/cancelled'
}
}, '#paypal-buynow');
paypal.version from your browser consolelogger.js:65 ppxo_button_pre_template_click {timestamp: 1505848188734, windowID: "2bda198901", pageID: "8143451158", referer: "developer.paypal.com", host: "developer.paypal.com", …}
print @ logger.js:65
log @ logger.js:175
warn @ logger.js:224
(anonymous) @ component.jsx:91
Thanks for the report @MaxDBN. We actually do a pre-render of the button while the final iframe loads. We have plans to optimize this and allow clicks to the pre-rendered button, I'll keep this open until we do.
For now, at least, testing with env: 'production' should be faster -- from the statistics we have, loading the iframe should only take 2-300ms in production mode.
Hello, i just also found this issue in the local sandbox development and i don't like it.
Trying to understand what problem this is solving by 'pre-rendering' the button.
Surely it'd be better to show a loading spinner, or even nothing at all, instead of a fake button which doesn't respond to clicks?
Maybe I'm misunderstanding something since I'm about to "display: none" this button thing for a little bit until it's actually ready. ¯_(ツ)_/¯
@DanielLeone -- the rationale is, in production mode, the button should be visible to the user immediately (so they can see paypal is a payment option), and by the time the button is clicked it should have had enough time to load. From our logs we see this is the case the vast majority of the time. Can I ask -- are you in sandbox or production mode? Sandbox mode can be significantly slower, which makes this problem appear a lot worse than it actually is.
In addition to sharing @DanielLeone's confusion initially, we're seeing stylistic changes to the button between when it has "pre-rendered" to when it has "fully rendered":
Pre-render:

Fully-rendered:

I agree with your rationale that it is nice to provide an indication that PayPal is an available payment method immediately rather than waiting, but this results in an odd user experience. I like to assume that this is a mismatch between the version we have installed and the most current version PayPal is serving to us. If so, this is another unfortunate side-effect of this forceful pre-loading.
@jkomusin -- are you using the CDN version of the script? Or if not, which version are you using?
4.0.166, looks to be .001 behind NPM.
Are you using it from the evergreen paypalobjects/api/checkout.js url, or hard-coding the version?
We are installing from NPM and building it into our single-page app's bundle, so occasionally we will have a stale version until our app is re-built and deployed. Bumping the version to 4.0.167 (again, from NPM) results in a subtler transition, but the subtext still fades out after loading.
OK. I would strongly recommend using https://www.paypalobjects.com/api/checkout.js -- this will ensure there's no difference between the initial render and the iframe render. It will also give performance benefits.
Is there any update on this issue, I am using https://www.paypalobjects.com/api/checkout.js and I still am able to click pay and nothing happened when the button first load
@bluepnume is there some class/attribute that we can check to know if the button is fully loaded or not?
Hi. Any update on this issue? I'm still experiencing the issue above where the button cannot be clicked right away.
I noticed that the button can only be clicked once the request below is done.
Request URL: https://www.paypal.com/webapps/hermes/api/logger
Request Method: POST
i am also facing this issue, this might decrease conversion ratio. I am using React button driver
Is there any temp workaround for this issue? E.g. checking if the iframe has loaded manually.
I noticed that the PayPalButton has something called prerenderIframe, and when the real iframe has loaded the prerenderIframe will get the class xcomponent-invisible
I will probably just do a setInterval with 200ms interval to check if the class has changed. Dirty hack, but it'll do for now.
UPDATE: Don't use this solution. Look at the comments below.
My final solution ended up looking like this:
The button itself, note that I'm assigning a ref to the button and I have the onDisplay event calling this.onDisplayPP:
<div className={classNames(this.state.ppButtonLoaded === false && 'hide')}>
<PayPalButton
ref={this.ppButton}
commit={true}
env="sandbox"
client={{
sandbox: '',
production: '',
}}
payment={(data, actions) => this.payment(data, actions)}
onAuthorize={this.onAuthorize}
onDisplay={this.onDisplayPP}
/>
</div>
And here's the onDisplayPP function:
onDisplayPP = (e) => {
if (this.ppButton.current && this.ppButton.current.state) {
this.ppInterval = setInterval(() => {
if (this.ppButton.current.state.parent.prerenderIframe.className.indexOf('xcomponent-invisible') > -1) {
clearTimeout(this.ppInterval)
this.setState({
ppButtonLoaded: true,
})
}
}, 300)
}
}
The state.ppButtonLoaded will determine if the iframe has loaded. You can display anything while it's loading, such as "Loading PayPal", etc.
Hope this helps anyone else, and PLEASE note that this could break at any time.
It seems that the onEnter event is more reliable
@godhand1607 Thanks, I wasn't aware of that event! Works a lot better, since onEnter is called when the invisible class is removed. Perfect.
Closing this; this issue is fixed in the new version of the sdk which is currently in beta. Will update here when it's available for general release.
@bluepnume I assume by new version you must mean v5? Because several versions have released since your post and I still have this issue.
Thanks for any clarification
Yep, new major version which will require a manual upgrade. Hoping to go public beta by the end of the month.
Adding my name to the people who need this feature. Not really sure why this issue is marked as closed when the release with the fix hasn't went live yet.
Please see:
https://developer.paypal.com/docs/checkout/
https://developer.paypal.com/docs/checkout/reference/upgrade-integration/
The latest script renders a button which is clickable from the moment it is rendered.
Just to be clear, if I'm using https://www.paypalobjects.com/api/checkout.v4.js it should be as simple as using v5 now?
Not quite. I'd recommend taking a look at the upgrade guide.
@bluepnume thanks for that. There's still one issue I can't figure out. I'm using the script in my React app and have the following in my render function:
<PaypalButton
env={env}
client={client}
payment={this.payment} // not functional as of upgrade
onApprove={this.onApprove}
onCancel={this.onCancel}
style={{
color: 'blue',
shape: 'rect'
}}
/>
I can't seem to figure out the new handler for payment. It doesn't work after upgrading and I'm not able to see the upgrade path in the docs
This is a serious issue that could be hurting conversion depending on the delay people are experiencing. For our setup the delay was around 2 seconds in production. The transition to the newer SDK is not clear when you're using a Braintree integration like ours. The issue was solved by initially rendering a button with the text "PayPal Loading..." and then changing that to the final button once enabled.
The key is to add .then(enabled) here: paypal.Button.render(renderOptions, '#paypal-button').then(enabled);
and then create some function enabled() that changes the button from your loading preview button to your final button. enabled() seems to be called well after the button is rendered and exactly at the moment it is enabled.
@davidyeager as mentioned, the latest version of the sdk does not have this issue. Please upgrade if possible. https://developer.paypal.com/docs/checkout/reference/upgrade-integration/
@bluepnume As @paypal/checkout-components is not available via ES6 imports (#1109) can you please fix this bug for v4.x as well?
v4 (still available at npm as paypal-checkout) is referenced by your support team and in the documentation that the support team uses to outline how to implement express checkout?
https://braintree.github.io/braintree-web/3.34.0/PayPalCheckout.html
Most helpful comment
Hello, i just also found this issue in the local sandbox development and i don't like it.