effect
elements man ui/behaviors/effectReactive side effects for a controller. effect runs a function now and
again whenever a reactive value it read changes, watchValue runs a callback
when one value changes, and untracked reads a value without subscribing to
it. A template reaches for them when something must happen as a value
changes rather than be rendered: showing a native <dialog>, pushing a
dismiss layer, locking scroll.
Signaturesfunction effect(fn: () => void): () => void; function untracked<T>(fn: () => T): T; function watchValue<T>(read: () => T, fn: (value: T, previous: T) => void): () => void;
| Function | Returns | What it does |
|---|---|---|
effect(fn) |
stop() |
Runs fn now and re-runs it whenever a reactive value it read changes. It runs detached from the render that created it, so a re-render of the parent never destroys it; only stop() does. |
untracked(fn) |
fn's result | Calls fn without subscribing the current computation to what it reads. Inside an effect, a value read this way does not re-run it. |
watchValue(read, fn) |
stop() |
Runs fn(value, previous) when read() returns a different value, compared with !==, and not on the first run. The callback itself is untracked. |
Start an effect in oninsert and stop it in onremove. An attribute read
inside the function is tracked, so the function re-runs when the caller
changes it.
In a template of your own
app/shared/templates/modal/index.ehtmlimport { effect, lockScroll } from "@elements/ui/behaviors"; interface ModalState { stop?: () => void; unlock?: () => void; } function sync(dialog: HTMLDialogElement, open: boolean, ui: ModalState) { if (open) { dialog.showModal(); ui.unlock = lockScroll(); } else { dialog.close(); ui.unlock?.(); } } <Modal (open: boolean = false, private ui: ModalState = {})> <dialog oninsert={(e) => ui.stop = effect(() => sync(e.target as HTMLDialogElement, open, ui))} onremove={() => { ui.stop?.(); ui.unlock?.(); }} onclose={() => open = false}> <slot/> </dialog> </Modal>
open is read inside the effect, so the dialog opens and closes as the
caller writes it, and onclose writes false back when the user presses
Escape.
Used by
effect: Checkbox (opens in a new tab), ColorPicker (opens in a new tab),
Field (opens in a new tab), NumberInput (opens in a new tab),
RadioGroup (opens in a new tab), Select (opens in a new tab),
Slider (opens in a new tab), TagsInput (opens in a new tab),
Toast (opens in a new tab), ToggleGroup (opens in a new tab),
Tree (opens in a new tab), VirtualList (opens in a new tab).
watchValue and untracked: most templates with a controller, from
Accordion (opens in a new tab) to Sidebar (opens in a new tab).