-
Notifications
You must be signed in to change notification settings - Fork 77
Description
Problem
As part of the move to a two-pass render system (diff + commit) in Crank 0.7, the schedule()
lifecycle method is now called just before flush()
, right before children are attached to their parent. This makes schedule()
almost redundant, as it no longer provides unique timing for custom logic. Previously, schedule()
would fire as soon as a component’s children had diffed, but now it will not fire until its (potentially async) siblings have been diffed as well.
However, if we allow schedule()
to return a promise, it can serve as a primitive for deferring the addition of a component’s DOM nodes to its parent. This enables advanced use-cases such as ordered mounting, coordination among siblings, and implementing features like SuspenseList (where siblings can "wait" for each other's completion before being committed to the DOM).
This would “rhyme” with the cleanup()
method, which in 0.7 can return a promise to defer the removal of DOM nodes, for animations and such.
Proposal
- Allow
schedule()
callbacks to return a promise. If a callback returns a promise, we defer the addition of the DOM nodes produced by the component until the promise fulfills. - Document and demonstrate advanced use-cases, including:
- Implementing SuspenseList-style ordered mounting using provisions for coordination.
- Staggered or animated reveals of sibling components.
- Preserving the double-render idiom seen in previous releases (
this.schedule(() => this.refresh())
).
Benefits
- Makes
schedule()
a non-redundant, powerful primitive in two-pass rendering. - Enables userland solutions for ordered async mounting (e.g., SuspenseList, staggered animations).
- Keeps the lifecycle API orthogonal:
schedule()
for (async) pre-commit,flush()
for post-commit,cleanup()
for (async) removal.