I'm trying to get two React applications to communicate by sending messages containing stringified objects.
The parent (http://localhost:3000) sends a message via postMessage
like this:
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"} />
iFrame (http://localhost:3001) does not receive the message, at least not immediately (I have to wait for react soft refresh to show the log).
The first error thrown 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').
P粉6708387352024-03-29 10:48:18
This is because when you call this postMessage()
method, your iframe document has not yet loaded, so the contentWindow
you receive is the original about:blank
one of the documents, not the one you expected.
One might say that the error message here is a bit confusing, and your development tools might be better off (also?) reporting that the source of the location is about:blank
(even if it is Check the origin
of the global document for postMessage()
).
But anyway, to solve the problem, wait for the load
event of <iframe>
. (Sorry, I'm not a reactJS ninja, so I'll let you find the best way to do this).
This is a trivial repro setup with the solution applied: https://jsfiddle.net/382pz5er/ (outsourced because StackSnippet's null origin frame is a bad example here).