Skip to main content

Events

Events flow one way — host → client — and are declared in the contract next to actions:

export const location = definePlugin(
'location',
{ get: action<void, Position>() },
{ events: { updated: event<Position>() } }
);

Subscribing (client)

Through usePlugin, event names are short and typed:

const { on } = usePlugin(location);

useEffect(
() =>
on('updated', (position) => {
// ^? Position
setPosition(position);
}),
[]
);

Or through the bridge directly with full names — useEvent('location.updated', handler) in React, bridge.on('location.updated', handler) anywhere.

Sending (host)

sendEvent is typed against the merged plugin event map — contract events get payload checking and autocomplete, while arbitrary custom event names stay allowed (an open event set):

const { sendEvent } = useBridgeHost({ plugins: [location.host(handlers)] });

sendEvent('location.updated', { lat: 37.5, lng: 127.0 }); // ✅ payload checked
sendEvent('location.updated', { lat: 'x' }); // ❌ compile error
sendEvent('app.custom', { anything: true }); // ✅ open set

Inside a plugin handler, ctx.emit uses short names and is typed against that plugin's events:

location.host({
get: async (_payload, ctx) => {
ctx.emit('updated', { lat, lng }); // ✅ typed
ctx.emit('nope', {}); // ❌ compile error
return { lat, lng };
},
});

Event schemas

event(schema) validates inbound event payloads on the client — invalid events are dropped, not delivered, and the failure surfaces through the global onError. See Schema validation.

Targeting

With multiple WebViews, events can be targeted to one or broadcast to all — see Multi-WebView routing.