I integrated the PayPal Plus iframe into my react app by appending the PayPal library js-script to the document in componentDidMount, updating the component state when the script is loaded and then calling the library method to initialize the PayPal Plus object. This renders the iframe into the placeholder div with the according id. I consulted the documentation (https://developer.paypal.com/docs/paypal-plus/germany/integrate/integrate-payment-wall/#) and did the aforementioned adaptations to use it in combination with my react app.
This works so far and looks like this in the minimalized example: page with rendered ppp iframe
In Firefox though, it isn't possible to navigate back by the browser's back button, once the iframe has been initialized. Instead, the whole component is loaded inside of the iframe. Like this: page after clicking back button
This doesn't happen in Chrome or Internet Explorer. Firefox version: 81.0 (64-Bit)
If I manually delete the iframe element from the DOM, the back button works normally again. I already tried using custom event handlers for the "popstate" and "beforeunload" events, to try to work around this but to no avail. Those events seemingly don't occur in the parent window in Firefox.
Steps to reproduce:
- Create react app (i used V16.13.1 in the example) (https://reactjs.org/docs/create-a-new-react-app.html#create-react-app).
- Insert provided classes into the project and use PppComponent in App.js.
- Acquire valid PayPal sandbox approvalUrl and set it on ppp config object.
- Run yarn or npm start.
- Open the app in Mozilla Firefox and click the back button of the browser.
This is basically the related code of the component:
import React from 'react';
import utils from './utils';
class PppComponent extends React.Component {
constructor() {
super();
this.state = {
scriptLoaded: false
}
}
componentDidMount() {
utils.appendScript(
'https://www.paypalobjects.com/webstatic/ppplus/ppplus.min.js',
() => this.setState({scriptLoaded: true})
);
}
componentWillUpdate(nextProps, nextState) {
if (nextState.scriptLoaded) {
this.initPaypalPlusIframe();
}
}
componentWillUnmount() {
utils.removeScript('https://www.paypalobjects.com/webstatic/ppplus/ppplus.min.js');
}
initPaypalPlusIframe() {
const pppConfig = {
approvalUrl: '{validApprovalUrl}',
placeholder: 'ppplus',
mode: 'sandbox',
language: 'de_DE',
country: 'DE',
useraction: 'commit',
};
window.PAYPAL.apps.PPP(pppConfig);
}
render() {
return (
<div>
<h1>Some Content Here</h1>
<div id="ppplus"/>
</div>
);
}
}
export default PppComponent;
And these are the util functions, used to append and remove the script:
class Utils {
appendScript(scriptToAppend, onLoad) {
const allSuspects = document.getElementsByTagName('script');
let doAppend = true;
if (allSuspects && allSuspects.length > 0) {
for (let i = allSuspects.length - 1; i >= 0; i--) {
if (allSuspects[i] && allSuspects[i].getAttribute('src') !== null
&& allSuspects[i].getAttribute('src').indexOf(`${scriptToAppend}`) !== -1) {
doAppend = false;
}
}
}
if (doAppend) {
const script = document.createElement('script');
script.src = scriptToAppend;
script.async = false;
script.onload = () => onLoad();
document.body.appendChild(script);
}
}
removeScript(scriptToRemove) {
const allSuspects = document.getElementsByTagName('script');
for (let i = allSuspects.length - 1; i >= 0; i--) {
if (allSuspects[i] && allSuspects[i].getAttribute('src') !== null
&& allSuspects[i].getAttribute('src').indexOf(`${scriptToRemove}`) !== -1) {
allSuspects[i].parentNode.removeChild(allSuspects[i]);
}
}
}
}
export default new Utils();
Has anybody an idea why this happens or maybe experienced something similar and knows how to fix/workaround this behavior?
I'd be glad about any help.
Thank You in advance.