Loading
wybthon.loading¶
loading
¶
Loading and Reveal: fallback UI for async computations.
Loading is the async boundary (SolidJS 2.0's
Loading, the successor to Suspense). It covers initial
readiness: any read of an async computation under the boundary that
raises NotReadyError registers the
computation with the boundary, and the boundary shows its fallback
until every registered computation has produced its first value.
Once content is on screen the boundary gets out of the way. A recompute
of an async memo that already has a value is a transition: the parts
of the UI that depend on the changed input hold their previous state
until the new value lands, and the boundary never shows its fallback
again. Use is_pending to render inline refresh
hints. Pass on= to opt back into the fallback for specific changes
(swapping the record being shown rather than refreshing it).
Reveal coordinates multiple Loading boundaries
beneath it, controlling the order their contents reveal (order) and
whether every pending boundary shows its own fallback (collapsed).
Example
See Also
Functions:
| Name | Description |
|---|---|
Loading |
Show a fallback while async reads under the boundary aren't ready. |
Reveal |
Coordinate the reveal order of multiple |
Loading
¶
Show a fallback while async reads under the boundary aren't ready.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
children
|
Any
|
Content rendered when nothing is loading: a VNode, a
zero-arg callable, or a list of either. Async computations
read anywhere in this subtree self-register with the
boundary when a read raises
|
None
|
fallback
|
Any
|
VNode, string, or callable returning one of those, shown while any registered async computation has no value. |
None
|
on
|
Any
|
An accessor, or list of accessors, naming the boundary's
inputs. The boundary waits for them initially even if the
children never read them, and when one of them changes
while data under the boundary is pending, the fallback
shows again instead of the old content being held. Use it
for "new record, fresh boundary" (a route's |
None
|
Returns:
| Type | Description |
|---|---|
VNode
|
A component |
VNode
|
fallback and children. |
Reveal
¶
Reveal(children: Any = None, *, order: RevealOrder = 'sequential', collapsed: bool = False) -> VNode
Coordinate the reveal order of multiple Loading boundaries.
Each Loading boundary mounted underneath (that isn't nested
inside another boundary) registers with the Reveal in mount
order, and the Reveal decides when each may show its content and
whether it shows its fallback. A Reveal nested inside another is
one composite slot in the parent's order: its boundaries stay on
their fallbacks until the parent releases the slot, then follow the
inner order.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
children
|
Any
|
Content containing one or more |
None
|
order
|
RevealOrder
|
|
'sequential'
|
collapsed
|
bool
|
Only consulted with |
False
|
Returns:
| Type | Description |
|---|---|
VNode
|
A component |
Example
Note
Every boundary's content mounts immediately (parked
off-document while pending), so all of them load in parallel;
order only controls when each is revealed.
What's in this module¶
Loading is the async boundary. Any read of an async
computation under it that raises NotReadyError
registers that computation with the boundary, and the boundary shows
its fallback until every registered computation has a first value.
Content stays mounted the whole time, parked off-document, so async
memos created inside it keep running and nothing is torn down.
Revalidations never re-trigger the boundary: a recompute of a memo that
has a value is a transition, which holds the affected UI on the old
state until the new value lands, and is_pending
is the tool for inline refresh hints. on= names inputs whose change
should show the fallback again instead (a new record, not a refresh).
Reveal coordinates several Loading boundaries
beneath it: the order their contents appear and how many fallbacks show
at once.
| Name | Description |
|---|---|
Loading |
Loading(children, *, fallback=None, on=None); children is a VNode, callable, or list; on is an accessor or list of accessors the boundary waits for, and whose change shows the fallback again. |
Reveal |
Reveal(children, *, order="sequential", collapsed=False); order is "sequential", "together", or "natural"; collapsed=True shows only the next fallback in a sequential group. |
from wybthon import Loading, Prop, Reveal, component, create_memo, div, is_pending, p, span
@component
def UserCard(user_id: Prop[int]):
async def load_user():
uid = user_id() # tracked: refetches when it changes
return await fetch_json(f"/api/users/{uid}")
user = create_memo(load_user)
return Loading(
lambda: div(
p(lambda: user()["name"]),
span(lambda: "Refreshing..." if is_pending(user) else ""),
),
fallback=lambda: p("Loading..."),
)
@component
def Dashboard(settings: Prop[object]):
return Reveal(
[
Loading(UserCard(user_id=1), fallback=p("Loading user...")),
Loading(Activity(), fallback=p("Loading activity..."), on=settings),
],
collapsed=True,
)
on=makes the boundary wait for specific accessors even if the children never read them, and when one of them changes while data under the boundary is pending, the fallback shows again instead of the old content being held.- With
order="sequential"contents reveal in DOM order, each waiting for the ones before it;"together"reveals all at once;"natural"lets each boundary reveal on its own data. Withcollapsed=Trueonly the next pending fallback shows. - Every boundary's content mounts immediately, so all of them load in
parallel;
orderonly controls when each is revealed. ARevealnested inside another is one slot in the parent's order; boundaries nested inside another boundary coordinate with that boundary.
See also¶
create_memo(async memos),latest,resolve,refresh- Error boundary:
Erroredfor the failure side - Lazy loading: lazy components suspend into the nearest
Loading - Concepts: Async and loading
- Examples: Async fetch