A small React + Vite demo that shows how window.postMessage works between a parent window and an embedded iframe.
This project demonstrates:
- sending messages from a parent page to an iframe
- listening for incoming messages inside the iframe
- updating a Leaflet map based on the message
- sending a response back to the parent
- logging both outgoing and incoming message traffic in the UI
Related article:
- Understanding
window.postMessageandwindow.parent.postMessagein JavaScript: https://medium.com/@mrajaeim/understanding-window-postmessage-and-window-parent-postmessage-in-javascript-f09d4eac68ba
- React-based UI for selecting a country
- Inline iframe with a Leaflet map
- Two-way communication using
postMessage - Live message log to visualize requests and responses
- Easy-to-run Vite setup for local experimentation
The app renders a parent interface with country buttons. Clicking a country sends a message like:
{ country: 'Japan' }to the iframe using:
iframeRef.contentWindow.postMessage(message, '*');Inside the iframe, a message listener receives the event and updates the map view. Once the map moves, the iframe sends a confirmation back to the parent via:
window.parent.postMessage(
{
type: 'confirmation',
message: 'Map moved to Japan'
},
'*'
);The parent window listens for incoming messages and displays them in a message log.
- React
- Vite
- JavaScript
- HTML
- CSS
- Leaflet (embedded in the iframe)
- Tailwind CSS
.
├── index.html
├── package.json
├── vite.config.js
├── tailwind.config.js
├── postcss.config.js
├── eslint.config.js
├── src
│ ├── App.jsx
│ ├── index.css
│ └── main.jsx
├── public
├── LICENSE
├── README.md
└── package-lock.json
- Node.js 18+
- npm
npm installnpm run devThen open the local Vite URL in your browser (usually http://localhost:5173).
npm run buildnpm run previewThis example intentionally uses '*' as the target origin for simplicity, but in real applications you should avoid that.
Use a specific origin instead:
iframeRef.contentWindow.postMessage(message, 'https://example.com');And validate incoming messages before acting on them:
window.addEventListener('message', (event) => {
if (event.origin !== 'https://example.com') return;
if (event.data && typeof event.data.country === 'string') {
// safe to use
}
});postMessage is a core browser API used for:
- parent ↔ iframe communication
- cross-window messaging
- embedded widgets and dashboards
- secure messaging between trusted pages
This repo is meant as a learning-focused example to make that communication easy to understand.
MIT