Skip to content

API

For the page that owns the <iframe>.

Export Signature Guide
Frame <Frame head? copyStyles? resize? srcDoc? {...iframeProps}> Portal
useFrame () => { window, document } Portal
useIframe ({ srcDoc? }) => { frameProps, iframe, window, document, mountNode, error } Portal
useIframeResize (target, options?) => { width, height } | null Resize
useIframeRPC <Remote, Local>(target, options?) => { remote, emit, status, error } RPC
useIframeEvent <Remote, Name>(target, name, handler, options?) => void RPC
useIframeTitle (target, { origin? }?) => string | null RPC
useIframeInert (target, inert, { origin? }?) => void Accessibility
useIframeLoad (target, { timeout? }?) => 'idle' | 'loading' | 'loaded' | 'timeout' Third-party iframes
withOptions (remote.method, { signal?, timeout? }) => sameSignature RPC
transfer (value, transferables) => value RPC
IframeKitError, RemoteError, TimeoutError, isIframeKitError Errors

target is an HTMLIFrameElement, null, or a ref to one. A ref is read after every commit of the component that calls the hook. If the <iframe> is rendered by another component that re-renders on its own, pass the element instead, e.g. from state set by a callback ref.

Every hook that talks to the iframe (useIframeResize, useIframeRPC, useIframeEvent, useIframeTitle, useIframeInert) shares one connection per iframe, and takes the same connection options (IframeConnectionOptions): origin, unsafeAllowAnyOrigin and debug. debug is on for the iframe as soon as any hook on it asks.

Option Default
origin the origin of the iframe’s src Expected origin of the iframe.
unsafeAllowAnyOrigin false Required to pass origin: '*'.
methods Methods the iframe may call. The latest ones are always used.
timeout 10_000 Per call, from send to result; Infinity allowed.
connectTimeout 30_000 How long to wait for the connection: queued calls reject, and status becomes 'timeout', after this long; Infinity allowed.
debug false Log all protocol traffic.

Runtime validation for either side, with any Standard Schema library. Next release.

Export Signature
validateArgs (schema, method) => method — the schema validates the arguments as a tuple; invalid ones reject with RIK_VALIDATION.
validatePayload (schema, handler) => handler — an invalid payload is reported with reportError and not delivered.
StandardSchemaV1, ValidationIssue types

See Validating what arrives.

The page that owns the <iframe>, without React: a widget’s loader script, a site that isn’t a React app. Also available as a <script> (dist/host.global.js, global ReactIframeKitHost). Next release.

Export Signature Guide
connectToIframe <Remote, Local>(iframe, options?) => IframeHandle Embedding a widget
withOptions, transfer as above
IframeKitError, RemoteError, TimeoutError, isIframeKitError
Option Default
origin, unsafeAllowAnyOrigin, debug As for the hooks.
methods, timeout, connectTimeout As for useIframeRPC.
resize off true sizes the height to the page’s reports; or { axis, minWidth, maxWidth, minHeight, maxHeight }.
syncTitle false Sets the iframe’s title attribute to the page’s title, and restores the original after.
onStatusChange (status: 'connecting' | 'connected' | 'timeout') => void, on every change.
onResize (size) => void, for every size the page reports.
onResizeLoop Called when the page’s feedback-loop guard starts holding growth.

IframeHandle: status, size ({ width, height } | null), title (string | null), remote, emit(name, payload?), on(name, handler) => off, setInert(inert), whenConnected(), dispose(). It shares the iframe’s connection with any hooks on the same iframe. Invalid options throw, as with connectToParent.

For the page inside the iframe. No React needed; also available as a <script> (dist/child.global.js, global ReactIframeKit).

Export Signature
connectToParent <Remote, Local>(options) => ParentHandle
withOptions, transfer as above
IframeKitError, RemoteError, TimeoutError, isIframeKitError

connectToParent options: allowedOrigins (required; origin strings, anchored RegExps or (origin) => boolean predicates), unsafeAllowAnyOrigin, methods, timeout, connectTimeout, autoResize (true or { measure }), syncTitle, debug.

connectToParent without RPC and events, for a page that only needs autoResize, syncTitle and inert: about 4 kB instead of 6 kB. Same options minus methods, timeout and connectTimeout; the handle has status, whenConnected() and dispose(). A call from the parent is answered with RIK_METHOD_NOT_FOUND. It shares the page’s connection with the full connectToParent, so both can be used on one page. Also exports IframeKitError and isIframeKitError, and ships as dist/child-lite.global.js.

ParentHandle: status ('idle' | 'connecting' | 'connected'), remote, emit(name, payload?), on(name, handler) => off, whenConnected(), dispose().

On the server, and when the page isn’t inside an iframe, connectToParent does nothing and stays 'idle'.

Export Signature
useParent <Remote, Local>(options) => { remote, emit, status, error }
useParentEvent <Remote, Name>(name, handler) => void

useParent takes the same options as connectToParent, read once on mount, except methods, which always uses the latest. It returns status: 'idle' during server rendering and hydration, and 'timeout' after connectTimeout without a parent that completes the handshake (for example, the page is framed by a site that doesn’t use the library); like useIframeRPC’s, it moves on to 'connected' if the handshake completes later.

For your tests, in jsdom or happy-dom. No React needed.

Export Signature Guide
mockChild <Remote, Local>(iframe, { methods?, origin?, timeout?, connectTimeout? }?) => MockChild Testing
mockParent <Remote, Local>({ methods?, origin?, timeout?, connectTimeout? }?) => MockParent Testing

MockChild: status, inert, remote, emit(name, payload?), on(name, handler) => off, resize({ width, height }), setTitle(title), whenConnected(), dispose().

MockParent: status, remote, emit(name, payload?), on(name, handler) => off, size, title, whenConnected(), dispose().

For development, on either page. No React needed.

Export Signature
onProtocolMessage (listener: ({ direction, message, detail? }) => void) => off
connectReduxDevTools ({ name?, maxAge? }?) => stop: sends every message to the Redux DevTools extension
summarizeProtocolMessage (message) => string, e.g. call getUser #q9x7c1

direction is '→' for a message this page sent and '←' for one it received. detail (which call a result answers, and how long it took) is only filled in by development builds with debug: true.

Type
Side<{ methods?, events? }> One side’s contract. Rejects non-cloneable types and reserved names.
Remote<S> The shape of remote for side S: every method returns a promise.
LocalMethods<S> Any subset of S’s methods, sync or async.
Emit<S>, On<S> emit and on for S’s events.
AnySide The default when no contract is given.