Liking cljdoc? Tell your friends :D

hyper.lifecycle

View lifecycle vocabulary shared across page handlers (and, later, reactive sub-regions and async workers).

Hyper page handlers climb a Reagent-style form ladder, chosen by the ownership question "what does this view own?":

  • form-1 — owns nothing. A pure (fn [req] -> hiccup). This is the default and needs nothing from this namespace.

  • form-2 — owns only framework-managed subscriptions (auto-cleaned). The handler returns a setup closure that runs once per mount and returns the pure render fn:

    (fn [req] ;; setup — runs once, effects allowed (h/watch! some-source) (let [data* (h/tab-cursor :data)] (fn [req] ;; render — runs every render, must be pure [:div @data*])))

  • form-3 — owns an external resource that needs explicit teardown. The handler returns a View (via view) whose :mount allocates the resource and returns it; the framework threads that value into :render and :unmount:

    (h/view {:mount (fn [] (open-conn! ...)) :render (fn [conn req] [:div (query conn)]) :unmount (fn [conn] (close! conn))})

There is deliberately no per-view mutable ctx slot: the server is always in declarative-rerender mode, so a resource opened at mount, read during renders, and closed at unmount is simply a value threaded immutably through the lifecycle.

View lifecycle vocabulary shared across page handlers (and, later,
reactive sub-regions and async workers).

Hyper page handlers climb a Reagent-style form ladder, chosen by the
ownership question "what does this view own?":

- **form-1** — owns nothing.  A pure `(fn [req] -> hiccup)`.  This is the
  default and needs nothing from this namespace.

- **form-2** — owns only framework-managed subscriptions (auto-cleaned).
  The handler returns a *setup* closure that runs once per mount and
  returns the pure render fn:

    (fn [req]                 ;; setup — runs once, effects allowed
      (h/watch! some-source)
      (let [data* (h/tab-cursor :data)]
        (fn [req]             ;; render — runs every render, must be pure
          [:div @data*])))

- **form-3** — owns an external resource that needs explicit teardown.
  The handler returns a `View` (via `view`) whose `:mount` allocates the
  resource and *returns* it; the framework threads that value into
  `:render` and `:unmount`:

    (h/view
      {:mount   (fn []         (open-conn! ...))
       :render  (fn [conn req] [:div (query conn)])
       :unmount (fn [conn]     (close! conn))})

There is deliberately no per-view mutable `ctx` slot: the server is
always in declarative-rerender mode, so a resource opened at mount,
read during renders, and closed at unmount is simply a value threaded
immutably through the lifecycle.
raw docstring

render-pageclj

(render-page app-state* tab-id handler req render-error-fn wrap-mw)

Resolve and render a page handler through the form-1/2/3 ladder, managing the per-tab page-view lifecycle and the render purity guard.

Returns the raw render result — a hiccup vector/seq, or a Ring response map (when a handler returns {:status …}), which the caller passes through unchanged.

Arguments:

  • app-state* — the app-state atom
  • tab-id — the tab being rendered
  • handler — the route's render fn (form-1/2/3 producer), already re-resolved from live routes by the caller
  • req — the request/context map
  • render-error-fn — (fn [error req] -> hiccup) error boundary
  • wrap-mw — (fn [render-fn] -> render-fn) applying the render-middleware chain (use identity for none)

The mount boundary is keyed on [handler path-params]: a page (re)mounts on first render, on handler-identity change (navigation, Var redefinition), and on a route path-param change (the same handler serving a different path-param value). A superseded mount is unmounted first — its form-3 resource and mount-scoped subviews (h/watch!, h/spawn!, async) are torn down, and the new mount re-acquires whatever is scoped to the new path-params. Query-param changes (filters, pagination — cursor-backed view state) re-render in place. form-1 re-runs its body every render.

Resolve and render a page handler through the form-1/2/3 ladder, managing
the per-tab page-view lifecycle and the render purity guard.

Returns the raw render result — a hiccup vector/seq, or a Ring response
map (when a handler returns `{:status …}`), which the caller passes
through unchanged.

Arguments:
- app-state*      — the app-state atom
- tab-id          — the tab being rendered
- handler         — the route's render fn (form-1/2/3 producer), already
                    re-resolved from live routes by the caller
- req             — the request/context map
- render-error-fn — `(fn [error req] -> hiccup)` error boundary
- wrap-mw         — `(fn [render-fn] -> render-fn)` applying the
                    render-middleware chain (use `identity` for none)

The mount boundary is keyed on `[handler path-params]`: a page (re)mounts
on first render, on handler-identity change (navigation, Var redefinition),
and on a route **path-param** change (the same handler serving a different
path-param value).  A superseded mount is unmounted first — its form-3 resource and
mount-scoped subviews (`h/watch!`, `h/spawn!`, async) are torn down, and the
new mount re-acquires whatever is scoped to the new path-params.  Query-param
changes (filters, pagination — cursor-backed view state) re-render in place.
form-1 re-runs its body every render.
sourceraw docstring

run-unmount!clj

(run-unmount! stored)

Run a stored page-view's :unmount (form-3 only), with effects allowed. Swallows and logs exceptions so teardown never breaks a render or disconnect cleanup.

Run a stored page-view's :unmount (form-3 only), with effects allowed.
Swallows and logs exceptions so teardown never breaks a render or
disconnect cleanup.
sourceraw docstring

teardown-page-view!clj

(teardown-page-view! app-state* tab-id)

Tear down a tab's page-view (running a form-3 :unmount) and remove it. Called from cleanup-tab! on disconnect.

Tear down a tab's page-view (running a form-3 :unmount) and remove it.
Called from cleanup-tab! on disconnect.
sourceraw docstring

viewclj

(view {:keys [mount render unmount] :as spec})

Construct a form-3 View from a map.

Keys:

  • :render (required) (fn [resource req] -> hiccup). resource is the value returned by :mount (nil when there is no :mount).
  • :mount (optional) (fn [] -> resource). Runs once when the view mounts. Its return value is the resource threaded into :render and :unmount.
  • :unmount (optional) (fn [resource] -> any). Runs once when the view unmounts (route change, re-mount, or tab disconnect).

A View is a distinct record type — not a bare map — so page dispatch can tell it apart unambiguously from a hiccup vector, a form-2 render fn, or a Ring response map.

Construct a form-3 `View` from a map.

Keys:
- :render  (required) `(fn [resource req] -> hiccup)`.  `resource` is the
           value returned by `:mount` (nil when there is no `:mount`).
- :mount   (optional) `(fn [] -> resource)`.  Runs once when the view
           mounts.  Its return value is the resource threaded into
           `:render` and `:unmount`.
- :unmount (optional) `(fn [resource] -> any)`.  Runs once when the view
           unmounts (route change, re-mount, or tab disconnect).

A `View` is a distinct record type — not a bare map — so page dispatch
can tell it apart unambiguously from a hiccup vector, a form-2 render
fn, or a Ring response map.
sourceraw docstring

view?clj

(view? x)

True when x is a form-3 View.

True when x is a form-3 `View`.
sourceraw docstring

cljdoc builds & hosts documentation for Clojure/Script libraries

Keyboard shortcuts
Ctrl+kJump to recent docs
Move to previous article
Move to next article
Ctrl+/Jump to the search field
× close