-
Notifications
You must be signed in to change notification settings - Fork 0
Open
Description
Problem
The current hook system has use_interval, use_mount, and use_unmount — all synchronous callbacks. There's no use_effect (run a side effect when dependencies change) and no way to do async work inside a component.
In atuin, async work (streaming responses, API calls) lives entirely outside the component tree — spawned as tokio tasks that communicate back via Handle::update(). This works, but it means the component can't own its own async lifecycle. If a component is unmounted while its async work is in flight, there's no automatic cancellation.
What iocraft does
use_future()— run an async closure tied to the component's lifetime. Cancelled on unmount.use_effect()— run a side effect when hash-based dependencies change. Synchronous, but combined withuse_futurecovers most patterns.
Questions to explore
use_effect(deps, callback):
- When deps change, run callback. Classic React pattern.
- Dependency tracking: hash-based (like iocraft)? Explicit dep list? Or rely on the fact that
lifecycle()is already re-called when props/state change, so effects declared conditionally already "react" to changes? - Cleanup: should
use_effectreturn a cleanup function that runs before the next effect or on unmount?
Async in components:
- A
use_asyncoruse_futurehook that spawns a tokio task tied to the component's lifetime. On unmount, the task is cancelled (AbortHandle). - The task would need a way to update the component's state — either a channel back to the framework, or a
State<T>handle (like iocraft's copy-based state). - This is deeply tied to the runtime model. Today, state mutation happens through
Tracked<S>with framework-driven dirty checking. Async tasks would need a way to trigger re-renders from outside the normal lifecycle.
Relationship to Handle:
Handle::update()already solves "async work updates state" at the application level. The question is whether per-component async is worth the complexity, or if the Handle pattern is good enough.- Per-component async is most valuable when components are reusable and self-contained (e.g., a
StreamingMarkdowncomponent that owns its own streaming connection). If components are always app-specific, Handle is fine.
No concrete proposal yet
This needs more real-world pain to drive the design. Capturing it here so we don't lose the thread.
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels