React cookbook
Patterns for @shardwire/react: connection lifecycle, strict manifests, and avoiding unnecessary reconnects.
This guide assumes you already followed Getting started and use shardwire/client (not the shardwire root import) in the browser bundle.
Connection state
useShardwire() returns a discriminated union: connecting → ready | error. Call useShardwireListener(...) unconditionally and let the hook wait for ready; render UI from status before invoking actions or reading ready-only fields.
useShardwireApp() returns AppBridge | null: null while connecting or on error, and the bridge instance when status === 'ready'—a small helper if you only need the client reference.
Capabilities
Use useShardwireCapabilities() to read the current negotiated capabilities and useShardwireCapability({ kind, name }) to explain whether a built-in event or action is currently allowed. This is the easiest way to gate UI without manually inspecting raw capability arrays.
useShardwireListener from context
Inside ShardwireProvider, you can call useShardwireListener({ event, onEvent, filter?, enabled? }) with a single argument. The hook subscribes when the provider connection is ready (and when enabled is not false). You do not pass AppBridge or duplicate enabled: conn.status === 'ready'.
The two-argument form useShardwireListener(app, props) is still supported (for example with useShardwireConnection and no provider).
useShardwireAction
Prefer useShardwireMutation(actionName) for new code. It exposes invoke, isPending, lastResult, lastError, and reset for AppBridge.actions. invoke rejects with an Error if the connection is not ready. lastResult stores the latest invocation result, including structured { ok: false } failures; lastError mirrors the latest thrown/not-ready error and action-failure message for simple alert UI. useShardwireAction(actionName) is the compatibility alias.
Event state
Use useShardwireEventState({ event }) when you just want the latest payload in component state, or pass initialState + reduce to derive list/counter/reducer-driven UI from event streams without hand-writing subscription glue.
Diagnostics import
diagnoseShardwireApp and formatShardwireDiagnosis are re-exported from @shardwire/react as well as shardwire/client, so dashboard code can depend on a single package entry when building error UI.
Preflight
Use useShardwirePreflight(desired, options?) to wrap app.preflight(...) in React state. The hook runs automatically by default and returns the latest report, status, and a refresh() function for re-check buttons.
Strict ready and manifests
With ready={{ strict: true, manifest, botIntents }}, the manifest must list every built-in event and action you rely on, and botIntents must cover catalog required intents for those events. If startup fails, use diagnoseShardwireApp and formatShardwireDiagnosis from @shardwire/react or shardwire/client (see Strict startup failed).
Reconnects and logger
useShardwireConnection reconnects when connection-affecting fields of options change (URL, secret, app name, debug, metrics callback identity, etc.) or when strict-startup ready inputs change (strict, manifest, botIntents, expectedScope). The logger callback identity is still ignored for that comparison so inline logger: { debug: () => ... } does not thrash connections. To swap loggers intentionally, remount the hook or set a parent key.
Filters and useShardwireListener
Inline filter objects are fingerprinted so { guildId } does not resubscribe every render. Still declare filter keys in defineShardwireApp under filters when using ready.strict — see Filters for an event not listed and Strict startup failed.
Further reading
@shardwire/reacton npm — see the package README foruseShardwireMutation,useShardwireEventState,useShardwireCapability,useShardwirePreflight, and test helpers- Troubleshooting → Vite
connectBotBridge