I have ReactJs Component which includes an iframe. That iframe is used to do some job and after it finishes it has callback to Success or Error pages. In my chrome browser, network tab I can see the requests and responses. I want to be able to handle those callbacks in frontend somehow, did any of you met this type of problem?
My project is MVC and I do not have Success and Error actions in my controllers, it is an single page application with React.
UPDATE my whole iframe looks like this
This iframe is third-party integrations which does a callback on success and error to static URL: host/controller/success and host/controller/error
My mission is to catch when this happens in React, I hope this is possible somehow, I was trying to listen to 'message' event, but might be that I am doing anything incorrect.
Any suggestions are appreciated
In React, developers use iframes to create either a sandboxed component or an application that is isolated from its parent component. In an iframe, when a piece of content is embedded from an external source, it is completely controlled by the source instead of the website it is embedded in.
We can simply use the ReactDOMServer. renderToString() to convert a react component to string and then set it to srcDoc attribute of iframe. The js event handlers like onClick don't work with this solution.
import React from "react"; import ReactDOM from "react-dom"; function App() { return ( <div className="App"> <h1>Iframe Demo</h1> <Iframe iframe={iframe} />, </div> ); } const rootElement = document. getElementById("root"); ReactDOM. render(<App />, rootElement);
To detect when the iFrame has finished loading, we need to add an event listener to the iFrame, and we need to return the removeEventListener function to remove the event listener if our component unmounts.
If you own the frame content you should use window postmessage to send content back to your page. https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage
If you are using MVC you can potentially add the postmessage listeners to your controller and send them to reply back to the view.
I've created a sample of what I was talking about.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<script src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.23/browser.min.js"></script>
</head>
<body>
<div id="app"></div>
<script src="./main.js" type="text/babel"></script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<script>
window.top.postMessage(
JSON.stringify({
error: false,
message: 'Here we go'
}),
'*'
);
</script>
</body>
</html>
// React controller used to load the iframe
class Loading extends React.Component {
render() {
return (
<div>
Waiting on iframe
<iframe src={this.props.iframeUrl}></iframe>
</div>
);
}
}
// React controller used after iframe postmessage
class Complete extends React.Component {
render() {
return (
<div>
iFrame postmessage got me here
</div>
);
}
}
// Sample of controller
class Controller {
constructor() {
this.loading = true;
this.onMessageReceived = this.onMessageReceived.bind(this);
this.bindEvents();
this.render();
}
bindEvents() {
window.addEventListener("message", this.onMessageReceived, false);
}
onMessageReceived(event) {
var data = JSON.parse(event.data);
console.log(data);
this.loading = false;
this.render()
}
render() {
if (this.loading){
ReactDOM.render(
<Loading iframeUrl="./iframe.html" />,
document.getElementById('app')
);
} else {
ReactDOM.render(
<Complete />,
document.getElementById('app')
);
}
}
}
// Run the controller
new Controller();
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With