Hicasso glossary¶
This glossary defines Hicasso-specific terms. Core re-frame2 terms such as app-db, frame, event, and subscription live in the core glossary.
Authoring¶
Hicasso¶
re-frame2's native React view adapter. Hicasso interprets
Hiccup, reads subscriptions with
h/sub, and accepts event vectors as intents. App-db,
events, effects, and the event pipeline remain ordinary re-frame2.
Require it as:
Forms, overlays, routing helpers, the native tier, and test tooling are separate optional namespaces.
Related: Getting started, Installation.
defview¶
h/defview defines a Hicasso view. The view receives one props map and
returns Hiccup, nil, a fragment, or a native React element at the direct-return
performance level.
Use a view as a Hiccup head. Do not call it as an ordinary function:
(h/defview counter [_]
[:main
[:h1 "Clicked " (h/sub [:counter/count]) " times"]
[:button {:on-click [:counter/increment]}
"Click me"]])
[counter {}] ;; view boundary
(counter {}) ;; raises
Related: Views and reads.
View¶
A function from a props map to markup, defined with h/defview.
In Hiccup head position it creates an independently re-rendering
boundary. A plain defn is an inline helper, not
a view.
Related: Views and reads.
Boundary¶
An independently re-rendering unit created by h/defview. It:
- tracks the body's
h/subreads; - compares props with ClojureScript
=; - supplies the re-frame2 frame used by event intents.
Native tags, fragments, and h/defhost heads do not create Hicasso
view boundaries.
Related: Views and reads.
Inline helper¶
An ordinary function called from a view body. Its returned Hiccup is included
in the caller's tree, and any h/sub calls belong to the enclosing
boundary. It does not create independent re-render behaviour.
A plain function in Hiccup head position raises
:rf.error/hicasso-bad-head.
Related: Views and reads.
h/sub¶
The only subscription-read form inside a Hicasso view. It is an ordinary
function call and may appear in a let, conditional, loop, or synchronous
helper.
A bare rf/subscribe in a view body is not an alternative. Native components
use n/use-sub.
Related: Views and reads.
Read-extent law¶
h/sub is legal only during direct synchronous execution of the active view
body, including helpers it calls immediately. A callback, promise, timer, lazy
sequence, unforced delay, or other deferred computation may not carry the read
outside that extent.
A read after the extent raises a structured error such as
:rf.error/hicasso-sub-outside-render or
:rf.error/hicasso-deferred-read-at-boundary. Read the value during render and
close over the value instead.
Related: Views and reads.
Collector¶
The runtime mechanism that records the subscriptions a boundary reads during one body execution. Commit reconciles that read set. An abandoned or retried render acquires no durable subscription ownership.
Related: Views and reads.
Component ABI¶
The props and children contract for a Hiccup head: which values are converted,
which pass by identity, where :key and :ref live, and how children arrive.
- Hicasso views receive a ClojureScript props map.
- Declared hosts follow their callback, slot, and server contracts.
- Native
n/$uses React slots and does not lower Hicasso event intents or controlled fields.
Related: Views and reads, Interop, The native tier.
Lowering¶
The conversion from Hicasso data to React props and elements. It includes the Hiccup walk, event-intent callback creation, controlled-field behaviour, and attribute normalisation.
When diagnostics identify lowering itself as the cost owner, the local escape
is a direct n/$ return from the same view.
Related: Events as data, The native tier.
Owned-wins merge¶
When a view forwards an attributes map into an element, literal keys written by
the element author take precedence. Control slots such as :value, handlers,
:key, and ::h/revision should not be replaceable through a
generic forwarded map.
Related: Views and reads, Controlled inputs.
Read topology¶
The placement and grouping of subscription reads relative to a collection.
| Shape | Behaviour |
|---|---|
| Fine | Each row reads its own entity; good for sparse updates |
| Coarse | One view-model represents the collection; good for cheap mount or bulk replacement |
| Chunked | One read covers a bounded block of rows |
| Windowed | Only visible rows exist in the DOM, usually through a virtualiser |
Related: Lists and collections.
Events and control¶
Intent¶
An event vector written directly at an event prop. The runtime creates a callback and dispatches the vector into the rendering view's frame.
The Hiccup tree retains the event as ordinary data, so tests and tools can
inspect it with =.
Related: Events as data.
h/event¶
The one marked callback form (HD-024). Expands to an ordinary function. The contract comes from the position where it is written: event positions dispatch a returned vector; render positions must stay pure; unclaimed host props refuse the mark.
[:input {:type "file"
:on-change (h/event [e]
[:upload/picked
(js/Array.from (.. e -target -files))])}]
Captures the rendering frame when created. Use it when arguments determine the
event — value-first foreign callbacks, file lists, drag data — or when the
body must call browser methods such as .preventDefault.
Related: Events as data, Interop.
h/frame¶
Returns the frame id keyword of the Hicasso boundary currently rendering. Legal only during a boundary body or a render callback that boundary supplied. Not a tracked subscription.
Exported today as h/hframe; substitute that spelling to run the sample below.
The difference is deliberate and is recorded under Status.
The taught carry spelling is composition with core:
Zero-arity ambient (rf/capture-frame) refuses under Hicasso's body
discipline. Prefer effects for application async work; use this at foreign
edges that retain a dispatching closure.
Related: Events as data.
::h/value and ::h/checked¶
Reserved markers replaced at dispatch with the event target's current value or checked state. Substitution occurs only at the top level of the event vector.
::h/value is the target's .value on every control but one. A
<select multiple>'s value is its selection rather than a scalar, so the marker
carries a vector of the selected option values — [] when nothing is picked.
Reading .value there would answer the first selected option only, which is a
plausible string that quietly is not what the user chose.
Related: Events as data, Controlled inputs.
::h/prevent¶
An intent wrapper that calls preventDefault and then dispatches one inner
event vector. Hicasso does not auto-prevent clicks; :on-submit is the one
position whose data spelling prevents by default, so a submit intent needs no
wrapper. A callback always owns its own event and is never auto-prevented.
Related: Events as data.
Controlled field¶
An input whose displayed value comes from app-db and whose user edits return as event intents. Hicasso's controlled path provides:
- synchronous same-turn convergence;
- committed-value echo;
- caret and selection preservation;
- IME composition safety;
- explicit reset through
::h/revision.
The native tier does not provide this repair. Keep controlled text fields on the interpreted Hicasso path.
Related: Controlled inputs.
::h/revision¶
A reserved prop for controlled text. Change it when the field should re-baseline to the current model value after a reset, rejection, rewrite, or server normalisation.
[:input
{:value (h/sub [:field/value id])
::h/revision (h/sub [:field/revision id])
:on-input [:field/edit id ::h/value]}]
Reset is not inferred from value equality. The exact namespaced keyword is
required; bare :revision is an ordinary attribute.
Related: Controlled inputs.
Buffered field¶
forms/buffered-field is an optional forms component that places an app-db
draft in front of a controlled model value. It supports commit, cancel,
rejection, rewrite, and revision-based reset.
Related: Forms.
Keyboard map¶
A map from DOM .key strings to event intents, used at :on-key-down or
:on-key-up.
Unlisted keys are ignored. There is no modifier DSL; use h/event
for cases such as Ctrl+Enter. Key maps suppress matches during IME composition.
Related: Events as data.
Interop¶
defhost¶
h/defhost declares a foreign React component once. The declaration can define:
- callback contracts:
:event,:handler, or:render; - ReactNode slots;
- a server policy;
- a Client-only fallback.
(h/defhost date-picker DatePicker
{:callbacks {:on-change :event}
:slots #{:calendar}
:server :client-only})
Keep the JavaScript require in a .cljs host namespace.
Related: Interop.
ReactNode slot¶
A host prop declared to contain React content, such as a modal title, footer, or Suspense fallback. Hiccup supplied to the slot is converted to React elements under the captured frame. Undeclared props receive Hiccup vectors as ordinary data.
Related: Interop.
as-element¶
h/as-element explicitly converts Hiccup to a React element for a render prop,
foreign callback, or other ReactNode position.
Related: Interop, Lists and collections.
as-component / outward bridge¶
h/as-component turns a Hicasso view into a real React component that a native
React, UIx, or JavaScript parent can mount under the existing frame provider.
It does not create another root or state owner.
Related: Interop.
Portal¶
h/portal renders Hiccup into another DOM container through React
createPortal while preserving frame and context. React events bubble through
the React tree rather than the DOM placement.
Use the overlay module instead when the UI should live on the browser's native top layer.
Related: Interop, Overlays and focus.
Server policy¶
The SSR contract for a host or native component:
- Render: execute on the server and produce deterministic React HTML;
- Client-only: do not execute on the server; produce a deterministic fallback or nothing until the browser adopts the root.
Foreign hosts and named native components default to Client-only. Native Hiccup and intrinsic React elements render by default.
Related: SSR and hydration, Interop.
Raw escape (:>)¶
[:> Component props ...] mounts a foreign React component without a lasting
host declaration. It is useful for migration or a true one-off. Repeated
crossings should use h/defhost so callback contracts, slots, and
server policy remain explicit.
Related: Interop.
Native tier¶
Native tier¶
The optional re-frame.hicasso.native namespace, usually aliased n. It
provides direct React element construction and named native components.
[...] always means interpreted Hiccup. n/$ always means native React.
Nothing silently compiles or promotes one form into the other.
Related: The native tier.
n/$¶
A macro that constructs one React element directly. It does not perform Hiccup lowering, intent conversion, class collection merging, controlled-field repair, or automatic Hiccup-child conversion.
Use h/as-element when one native subtree needs an interpreted Hiccup child.
Related: The native tier.
n/props¶
A syntactic marker telling n/$ that a dynamic expression is its props
operand. It creates no runtime wrapper.
Without the marker, an arbitrary dynamic map in second position is treated as a child.
Related: The native tier.
n/defcomponent¶
Defines a named top-level React function component with Hicasso's native-tier marker, source identity, display name, and server policy. Ordinary React hooks are legal inside it.
Use n/use-sub and n/use-frame to join the current
re-frame2 frame.
Related: The native tier.
n/use-sub¶
A React hook that subscribes to a re-frame2 query in a native component. It obeys React's rules of hooks: call it unconditionally at the top level of the component.
Related: The native tier.
n/use-frame¶
A React hook returning frame-locked operations such as :dispatch,
:dispatch-sync, and :subscribe for the current native component.
Related: The native tier.
Native island¶
A named native React component under the same React root and re-frame2 frame as the surrounding Hicasso application. It is appropriate for hooks, vendor widgets, and high-rate host-private mechanics.
Xray names and times the crossing, while the inner React tree remains host-opaque.
Related: The native tier.
n/memo¶
Marker-preserving React memoisation for a named native component. Raw
react/memo can erase the marker used by Xray and embedding checks.
Related: The native tier.
n/lazy¶
Marker-preserving React.lazy loading for a named native component. It follows
React's promise-returning loader contract and retains the Hicasso native marker.
Declare it at namespace top level.
Related: Code splitting and lazy loading, The native tier.
Performance ladder¶
Five explicit implementation levels:
- ordinary Hicasso;
- tuned read topology;
- a direct native return from an existing view;
- a named native island;
- a native screen.
Related: Performance, The native tier.
Escape-benefit rule¶
Keep a native escape only when it:
- recovers at least 20% of the measured interaction;
- saves at least 2 ms at p95; or
- converts a failed user-visible budget into a pass.
Otherwise remove it.
Related: Performance.
State homes¶
One state owner¶
Application-visible state lives in re-frame2 app-db. Hicasso does not add a component-local reactive store. A host may retain private mechanics only when they are not a hidden duplicate of an application fact.
Related: Ephemeral state.
motion/presence¶
Optional exit-retention head from re-frame.hicasso.motion. Keeps keyed
children for :timeout-ms after their data leaves app-db so CSS exit
transitions can run. Applies ::h/mounting / ::h/unmounting attribute
overrides on elements, or passes :rf/phase to view children. Not an
animation system.
Related: Motion and presence, Ephemeral state.
Pressure valve¶
A legitimate home for UI state under the one-state-owner rule:
- an explicit app-db address;
- the forms module for drafts and form control;
- native host state for high-rate private mechanics;
- browser-owned state as an explicit interop choice;
- presence retention for pixels that outlive removed data.
Related: Ephemeral state.
Overlay¶
re-frame.hicasso.overlay popover and modal primitives. They use the browser's
native top layer. App-db owns :open?; :on-dismiss is an event; the browser
owns stacking, light-dismiss, modal focus trapping, and focus restoration.
A closed overlay has no DOM node, listener, or active body subscriptions.
Related: Overlays and focus.
route-link¶
A routing helper that returns a real anchor and encodes navigation as a Hicasso intent. It supports route ids and params, optional intent prefetch, native link semantics, and link-local veto behaviour.
It is an inline function, not a separate view. Active-state styling comes from a route subscription comparison.
Related: Routing and navigation.
View-scoped read¶
A resource whose lifetime is a local view rather than the current route. It has no dedicated mechanism: the event that decides the data is wanted ensures it under an owner, and the event that dismisses the view releases that owner.
(rf/reg-event :suggestions/wanted
(fn [_ [_ q]]
{:fx [[:dispatch [:rf.resource/ensure
{:resource :app/suggestions
:params {:q q}
:owner [:suggestions]
:cause [:suggestions/wanted q]}]]]}))
Resource subscriptions are passive in every case — they project the cache and never fetch. An owner pins its entry against GC until it is released.
Related: Async resources, Resources glossary.
Testing¶
Test kit¶
Two namespaces:
re-frame.hicasso.test, usuallyht, for pure and semantic tests;re-frame.hicasso.test.mounted, usuallyhm, for mounted React and DOM tests.
Related: Testing.
Testing ladder¶
| Level | Proves | Mechanism |
|---|---|---|
| L0 | Handlers, subscriptions, transitions | Pure function calls |
| L1 | Intents, codecs, revision laws, macro expansion | Data and property tests |
| L2 | One hook-free body as a semantic tree | ht/tree |
| L3 | React lifecycle, hooks, hosts, error boundaries | Mounted facade |
| L4 | IME, caret, focus, hydration, performance | Real browser engines |
A lower level does not prove the equality of a higher level.
Related: Testing.
Semantic harness¶
ht/tree runs one hook-free Hicasso view body with injected subscription
fixtures and returns a semantic tree. Nested views remain represented as calls.
Hooks, hosts, raw React elements, and n/$ results are refused and belong at
L3.
Related: Testing.
Mounted facade¶
The hm namespace for L3 tests. It provides isolated-frame mount and hydrate,
rerender, dispatch-and-settle, settle, virtual-clock advancement, unmount, and
assert-clean! residue checking.
Related: Testing.
Sabotage control¶
A deliberately broken twin of an important test or measurement. It proves that the instrument moves when the input is wrong and prevents an empty population from passing vacuously.
Related: Testing.
Canonical DOM¶
A normalised DOM serialisation used for differential comparison. Attribute names are ordered so equivalent DOM does not differ only because properties were inserted in a different sequence.
Canonical DOM is distinct from semantic-tree equality, exact server bytes, and hydrated browser behaviour.
Related: Testing, Migrating from Reagent.
Diagnostics¶
Causal lens¶
The diagnostic sequence used by Xray:
event
→ subscriptions recomputed
→ values changed
→ views notified
→ bodies run
→ React commit
→ browser paint
Render, commit, and paint are separate claims.
Related: Diagnostics.
Explain-render¶
Xray's answer to “why did this view run?” It reports the cause category, changed reads or props, current read set, fan-out, completeness, and evidence loss.
Related: Diagnostics.
Hot-view advisor¶
A diagnostic ranking that combines time, frequency, read churn, and fan-out, then classifies the pressure as computation, topology, lowering, React, or layout. It recommends the smallest credible remedy and never auto-promotes code to native.
Related: Diagnostics, Performance.
Loss labels¶
Explicit labels for incomplete evidence:
:unknown;:opaque/:no-static-analysis;:host-opaque;:cap;:uncorrelated.
Missing evidence is not represented as an empty result.
Related: Diagnostics.
Complaint catalogue¶
The stable :rf.error/* and :rf.warning/* identifier set, including cause,
recovery, and source links where available. Tests assert the id, not the human
message.
Related: Diagnostics.
Production erasure¶
Removal of development diagnostics, evidence machinery, source locations, and complaint messages from default release bundles. Optional performance timing has a separate compile-time flag and is disabled by default.
Related: Diagnostics.
Lifecycle and delivery¶
mount!, render!, and unmount!¶
The Hicasso root lifecycle.
h/mount! associates a DOM container, a frame, optional :initial-events, and
one root view. It returns a root handle. Initial events run in order before
first paint.
h/render! renders a new root element through the same handle.
h/unmount! tears the root down and is safe to call more than once.
(defonce root
(h/mount!
(js/document.getElementById "app")
{:frame :rf/default
:initial-events [[:app/init]]}
[app-shell {}]))
Related: Installation.
hydrate!¶
Two functions complete hydration:
re-frame.ssr/hydrate!installs the server payload into the client frame;h/hydrate!adopts existing server DOM for one Hicasso root.
State hydration must run before DOM adoption.
Related: SSR and hydration.
Error boundary¶
h/error-boundary is a React error region with :fallback, :reset-key, and
:on-error. It is different from a re-render boundary; only the
error boundary catches descendant render and lifecycle exceptions.
Expected failures remain ordinary app-db state.
Related: Errors.
User-visible budget¶
A performance requirement expressed as an observable user outcome, such as:
- discrete interaction paint within 50 ms p95;
- controlled echo within one frame;
- broad operation within 100 ms p95;
- zero teardown residue.
Synthetic benchmark scores do not replace these budgets.
Related: Performance.
Shadow comparison¶
A migration witness that mounts a reference implementation and candidate under isolated equivalent state, drives both with one script, and compares canonical DOM plus event-intent streams at each checkpoint.
Related: Migrating from Reagent.