Components
<Defer>: defers content into a placeholder. It renders its own placeholder, so it is self-sufficient<Slot>: a named placeholder, filled by a<Defer>that renders elsewhere in the tree
<Defer>#
Registers its children as deferred content and renders a placeholder in its
place, showing fallback (empty when omitted) until the content is ready. Its
id is generated, unless target names a <Slot> (below).
import { Defer } from "@vincle/flow";
<Defer fallback={<p>Loading dashboard…</p>}> <HeavyDashboard /></Defer>;Pass a factory to receive an AbortSignal. It fires when the client
disconnects or the fragment's timeout elapses; forward it to your own
cancelable work (e.g. fetch(url, { signal })) so that work stops early:
<Defer fallback={<p>Loading dashboard…</p>}>{(signal) => <HeavyDashboard signal={signal} />}</Defer>The signal does not cut the render short: if it has fired by the time the render
finishes, the result is discarded and routed to onError instead of being
emitted.
Merge types#
merge controls how the content applies to the target element:
merge |
Effect |
|---|---|
"replace" |
Target element is replaced (default) |
"append" |
Content inserted as last child of target |
"prepend" |
Content inserted as first child of target |
"before" |
Content inserted as previous sibling |
"after" |
Content inserted as next sibling |
"morph" |
Target is diffed against content in place |
"morph" keeps focus, scroll position and form state. Not every adapter
supports every merge type: an unsupported one is rejected at registration with a
clear error.
<Slot>: named insertion point#
A named placeholder for content deferred elsewhere in the tree: typically a
layout reserving a spot, filled by a page component that cannot reach into that
layout. Its children render immediately as placeholder content, until the
matching <Defer> replaces them. name is required.
When placeholder and content live in the same spot, skip Slot: Defer with
its own fallback does the job.
The <Slot> is the placeholder: its <Defer> emits none of its own, wherever
the two sit in the page.
import { Defer, Slot } from "@vincle/flow";import { Results } from "./results";
function SearchPage() { return ( <> <main> <h1>Search results</h1> <Slot name="results"> <p>Loading results…</p> </Slot> </main> <Defer target="results"> <Results /> </Defer> </> );}Content types#
Defer children (the DeferContent type) are a value, or a factory receiving
the AbortSignal and returning one:
| Content | Behaviour |
|---|---|
JSX.Element or string |
One patch, rendered once |
AsyncIterable<JSX.Element> |
A stream: one patch per item, as it comes |
The runtime consumes an AsyncIterable itself: no .then() or for await on
your side. See Streaming.
Props#
| Prop | Applies to | Meaning |
|---|---|---|
name |
Slot |
id of the placeholder (required) |
target |
Defer |
optional placeholder id; generated automatically when omitted |
fallback |
Defer |
placeholder content shown in the shell |
merge |
Defer |
how content applies to its target (default "replace") |
timeout |
Defer |
per-fragment render timeout in ms |
onError |
Defer |
per-fragment error handler, overriding the renderer's one |