Frame Link is a lightweight library that makes two way async communication, between a parent site and iframe, easy.
You need to have access to both the parent frame codebase and the target iframe.
Some version of frame-link must be installed in both.
frame-link: is the vanilla version "yarn add frame-link" see
frame-link-react ( this one ): uses React's context api along with react recoil to perform selective re-renders
yarn: yarn add frame-link-react
npm: npm i frame-link-react
<FrameLinkProvider>
<MyComponent /> or {children}
</FrameLinkProvider>
useEffect(() => {
registerTarget(window.parent)
}, [ready])
useEffect(() => {
registerTarget(iframeRef)
}, [ready])
const abcUpdater = usePostMessage('abc'); // Creates an updater for 'abc'
abcUpdater('hello world') // Sends 'hello world' to the other frame.
const abc = useSubscribe('abc'); // Subscribe to key 'abc' and update any time something is messaged to this key
See Examples
import { useContext, useEffect, useRef } from "react";
import FrameLinkProvider, { FrameLinkContext } from "../src/FrameLinkProvider";
export default function App() {
return (
<FrameLinkProvider>
<MyComponent />
<MyButtonComponent />
<MyNotificationComponent />
</FrameLinkProvider>
);
}
import { useContext, useEffect, useRef } from "react";
import { FrameLinkContext } from "../src/FrameLinkProvider";
function MyComponent() {
const { registerTarget, ready, connected } = useContext(FrameLinkContext);
const frameRef = useRef<any>();
useEffect(() => {
if (!!frameRef.current) {
registerTarget && registerTarget(frameRef.current);
}
}, [ready, frameRef]);
useEffect(() => {
console.log("connected", connected);
}, [connected]);
return (
<div>
<iframe ref={frameRef} src="www.something.com" />{" "}
</div>
);
}
import { useContext } from "react";
import { FrameLinkContext } from "../src/FrameLinkProvider";
function MyButtonComponent() {
const { usePostMessage } = useContext(FrameLinkContext);
const updateTest = usePostMessage("test");
return (
<button
onClick={() =>
updateTest({ myPayload: "this is a test" }, () => {
// Optional callback... well it is supposed to be. I need to fix the type
})
}
>
send test
</button>
);
}
import { useContext } from "react";
import { FrameLinkContext } from "../src/FrameLinkProvider";
function MyNotificationComponent() {
const { useSubscribe } = useContext(FrameLinkContext);
const testTwo = useSubscribe < { myPayload: string } > "test-two";
// This will update whenever "test-two" gets new data.
return <div>{testTwo?.myPayload}</div>;
}
import { useContext, useEffect, useRef } from "react";
import FrameLinkProvider, { FrameLinkContext } from "../src/FrameLinkProvider";
export default function App() {
return (
<FrameLinkProvider>
<MyComponent />
<MyButtonComponent />
<MyNotificationComponent />
</FrameLinkProvider>
);
}
import { useContext, useEffect } from "react";
import { FrameLinkContext } from "../src/FrameLinkProvider";
function MyComponent() {
const { registerTarget, ready, connected } = useContext(FrameLinkContext);
useEffect(() => {
if (ready && registerTarget) {
// Register the target ( in this case the parent )
registerTarget(window.parent);
}
}, [ready]);
useEffect(() => {
// Wait for them to connect ( sends a ping and gets a reply ping )
console.log("connected", connected);
}, [connected]);
return <div></div>;
}
import { useContext } from "react";
import { FrameLinkContext } from "../src/FrameLinkProvider";
function MyButtonComponent() {
const { usePostMessage } = useContext(FrameLinkContext);
const updateTestTwo = usePostMessage("test-two");
return (
<button
onClick={() =>
// Call the updater with the data to send to the other frame.
updateTestTwo({ myPayload: "this is a test-two test" }, (replyData) => {
// Optional callback... See subscribe
// If a reply callback is included, when this is received on the parent, we will send a response back
// If the parent includes a reply callback when subscribing, replyData will be whatever that callback returns.
})
}
>
send test
</button>
);
}
const optionalReplyFunction = (latestData) => {
return { anything: "you want" }; //
};
import { useContext } from "react";
import { FrameLinkContext } from "../src/FrameLinkProvider";
function MyNotificationComponent() {
const { useSubscribe } = useContext(FrameLinkContext);
const test =
useSubscribe < { myPayload: string } > ("test", optionalReplyFunction);
// This will update whenever "test-two" gets new data.
return <div>{test?.myPayload}</div>;
}