re-frame.adapter.helix¶
re-frame.adapter.helix binds re-frame2 to the Helix React substrate. It ships as its own artefact (day8/re-frame2-helix) and depends on re-frame.core, never the reverse. A Helix app requires this namespace and passes its adapter Var into (rf/init! ...). It exposes:
- the Helix-shaped hooks
use-subscribe,use-frame,use-resource-lease, anduse-current-frame; - the
frame-provider(SCOPE) +frame-root(ENSURE) components; - the
wrap-viewview-wrapping seam; - the
adapterspec.
The substrate-agnostic carry and scoping primitives (capture-frame, with-frame, with-new-frame) live on re-frame.core. The surface mirrors the UIx adapter one-for-one. For choosing between substrates, see Use UIx, Helix, or reagent-slim.
Initialisation¶
adapter¶
- Kind: Var (map)
- Signature:
- Description: The adapter spec passed to
(rf/init! ...). Implements the same adapter contract as the Reagent and UIx adapters.:kindis:rf.adapter/helix.
Hooks¶
use-subscribe¶
- Kind: Helix hook (function)
- Signature:
- Description: The hook-shaped equivalent of
subscribefor Helix components. Returns the current sub value and re-renders the calling component when it changes. - The 1-arg form resolves the frame through the surrounding scope: dynamic-var first, then React context. It raises
:rf.error/no-frame-contextwhen no frame is in scope. - The 2-arg form pins an explicit frame id.
use-frame¶
- Kind: Helix hook (function)
- Signature:
- Description: Returns the frame ops map for the ambient frame — exactly what
(rf/capture-frame)returns (the frame-locked ops map), captured in hook position. This is how a Helix component gets hold ofdispatch(and the other frame-locked ops) without auto-injection: destructuredispatchoff it and close over that.
capture-frame is the hold primitive; reg-view injection (Reagent) and use-frame (UIx / Helix) are its two ergonomic spellings — one primitive, three faces.
- Frame resolution matches
use-subscribe: dynamic-var scope first, then the surroundingframe-provider/frame-rootvia React context. It raises:rf.error/no-frame-contextwhen neither is in scope. - The returned map is reference-stable across re-renders for the same resolved frame (safe in effect deps and child props); a provider swap re-renders the caller and yields a map locked to the new frame.
- No options map, no variants — for an explicit frame, call
(rf/capture-frame frame-id)directly. - Example:
use-resource-lease¶
- Kind: Helix hook (function)
- Signature:
- Description: Holds a resource liveness lease for the calling component's mounted lifetime. On mount it dispatches
:rf.resource/ensurewith an app-minted[:lease …]owner; on unmount it dispatches:rf.resource/release-ownerfor that lease. Returns nil: it manages liveness only. Read the data withuse-subscribeon a[:rf.resource/*]query. descriptor— resource-instance identity{:resource … :scope … :params …}.opts—:cause(recorded on the ensure; defaults to[:lease :mount]) and:frame(pin to an explicit frame id, bypassing ambient resolution).- Without
:frame, the frame resolves through the same chain asuse-subscribe, raising:rf.error/no-frame-contextwhen no frame is in scope. - Inert unless the resources artefact (
day8/re-frame2-resources) is on the classpath to register the resource events. - Example:
use-current-frame¶
- Kind: Helix hook (function)
- Signature:
- Description: A raw React-context read of the frame keyword supplied by the surrounding
frame-provider(SCOPE) orframe-root(ENSURE) — both install the one shared React context. When neither sits above, it returns:rf.frame/no-provider— never a synthesised default. It consults the React-context tier only, not the dynamic-var tier; for the full resolution chain, use(rf/current-frame-id).
NOT USED — no call sites found in
implementation/,examples/, ortools/.
Components¶
frame-provider¶
- Kind: Helix component (function — SCOPE-only)
- Signature:
- Description: The Helix-shaped SCOPE-only frame provider (rf2-nyea0r split — roots ensure; providers scope; for create-if-absent, use
frame-root). Scopes an already-created frame; creates nothing. Children ride the$trailing-args channel (there is no:childrenprop-map key). - Fails loud if the frame is absent (
:rf.error/frame-provider-frame-absent). A nil:frameraises:rf.error/no-frame-context; a non-keyword raises:rf.error/bad-frame-provider-arg; an:id(the ENSURE key) raises:rf.error/frame-provider-given-id. - Example:
frame-root¶
- Kind: Helix component (function — ENSURE, a commit-owned two-pass boundary)
- Signature:
- Description: The Helix-shaped ENSURE component (rf2-nyea0r split). Creates the named frame if absent, or reuses it without re-seeding if present; never destroys the frame on unmount. Accepts
make-frameopts. A missing/nil/non-keyword:idraises:rf.error/frame-root-missing-id. Children ride the$trailing-args channel. - Commit-owned two-pass: the create/seed runs in a client
useLayoutEffect(at commit), not during render — children render only after the frame is live, and a render React discards before commit creates + seeds nothing (no ghost frame). - Re-mounting under the same
:id(hot reload, React StrictMode dev double-invoke) neither destroys durable state nor re-runs:initial-events. A mounted:id/opts change raises:rf.error/frame-root-reconfigured; a stray:frameraises:rf.error/frame-root-given-frame. - Example:
View wrapping¶
wrap-view¶
- Kind: function
- Signature:
- Description: Adapter-side source-coord injection. Wraps
user-fnin a function component that injectsdata-rf2-source-coordon the rendered root DOM element in debug builds. Production builds elide the injection and returnuser-fnunchanged. The returned fn has the same call signature asuser-fnand is suitable as a Helix component head. - Example:
Test and SSR seams¶
flush-views!¶
- Kind: function
- Signature:
- Description: Wraps React's
act()for tests. The 1-arity form calls(act f); the 0-arity form flushes pending effects. Returns nil. - Example:
set-hiccup-emitter!¶
- Kind: function
- Signature:
- Description: Installs a render-tree → HTML fn. This is the Helix side of the SSR late-bind seam, at parity with the Reagent and UIx adapters. Normally you don't call this directly; requiring
re-frame.ssrwires the emitter for you. Passnilto reset. - Example: