I’m trying to make two React Apps communicate by sending messages containing stringified objects.
The parent (http://localhost:3000) sends a message through postMessage
like so:
let iframe = document.querySelector("iframe")
useEffect(() => {
if (!!localStorageObject && !!iframe) {
iframe?.contentWindow?.postMessage(localStorageObject, "http://localhost:3001")
}
}, [localStorageObject, iframe])
// ...file and start of return
<iframe
style={{minHeight: window.outerHeight, width: '100%', border: "none"}}
referrerPolicy="strict-origin-when-cross-origin"
src={myUrlWithParams}
title="App"
allow="clipboard-write"
id={"iframe"}
/>
The iFrame (http://localhost:3001) does not recieve the message, at least not immediatly (I have to wait for a react soft refresh for the logs to show up).
The error thrown at first is:
Failed to execute 'postMessage' on 'DOMWindow': The target origin provided ('http://localhost:3001') does not match the recipient window's origin ('http://localhost:3000').
2
Answers
I only got the error when the postMessage second parameter was different than the iframe source, you can change that for a
*
to make sure not to get this error, also you should use a ref for the iframe.See if this helps you:
This is because your iframe document hasn’t loaded yet when you call this
postMessage()
method, and hence thecontentWindow
you receive is the one of the originalabout:blank
document, not your expected one.One could argue that the error message is a bit confusing here, and your dev tools could probably have been nicer by (also?) reporting that the location’s origin was
about:blank
(even if it’s the global document’sorigin
that’s been checked forpostMessage()
).But anyway, to workaround that issue, wait for the
load
event of your<iframe>
. (I’m sorry I’m not a reactJS ninja, so I’ll let you the work of finding the best way to do so).Here is a vanilla repro setup with the solution applied: https://jsfiddle.net/382pz5er/ (outsourced because StackSnippet’s null origined frames make for a bad example here).