Escape hatches
The bits that let non-React code reach into what the hooks are doing — and the errors you can catch.
Reaching the hooks’ instances
Section titled “Reaching the hooks’ instances”The hooks memoise one engine per name for the page. These hand you the same instance, not a new one:
import { getSharedStore, getLeader, DEFAULT_NAME } from 'use-everywhere';
getSharedStore(); // the store behind a bare useSharedState()getSharedStore('settings'); // …behind useSharedState(k, v, { store: 'settings' })getSharedStore('settings', 'tab'); // a different scope is a different storegetLeader('feed'); // the Leader behind useLeader({ name: 'feed' })This is how you write to shared state from outside a component — an event handler in a plain module, a service worker message, a Zustand middleware:
// Nowhere near React. Every tab sees it.getSharedStore('session').set('loggedIn', false);DEFAULT_NAME is the string the hooks default to ('use-everywhere'), exported
so you can target the same bus without hard-coding it.
Errors
Section titled “Errors”Both are real classes, so instanceof works:
import { WindowClosedError, HandshakeTimeoutError } from 'use-everywhere';
try { const receipt = await pay.result;} catch (err) { if (err instanceof WindowClosedError) { // The user closed the payment window before finishing. } if (err instanceof HandshakeTimeoutError) { // The opened page never called connectToOpener — wrong URL, or it crashed. }}useOpenedWindow catches these for you and turns them into render state
(status: 'closed-early'), so you only need them if you’re driving openWindow
by hand.
CID_PARAM
Section titled “CID_PARAM”The query-string parameter (ue_cid) that openWindow appends to the child’s
URL to carry the connection nonce. Exported because the child page may want to
strip it before it ends up in analytics or a history entry:
import { CID_PARAM } from 'use-everywhere';
const url = new URL(location.href);url.searchParams.delete(CID_PARAM);history.replaceState(null, '', url);Don’t try to forge it. It’s one of four things the child validates — origin, envelope brand, nonce, and source window — and none of them are optional. See the security model.
Types worth knowing
Section titled “Types worth knowing”Version | [counter, clientId] — see the clock |
MessageMeta | { clientId, kind, self } — who sent it, and whether it was you |
Peer | { id, kind, lastSeen } |
PeerKind | 'tab' | 'worker' | (string & {}) — open, so you can invent your own |
MessageMap | The shape you parameterise channels with |
BusWire | The discriminated union of everything on the bus |
PersistAdapter | Bring your own storage — see defineStore |