# effect Reactive 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 ``, pushing a dismiss layer, locking scroll. ```ts Signatures function effect(fn: () => void): () => void; function untracked(fn: () => T): T; function watchValue(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 ```ehtml app/shared/templates/modal/index.ehtml import { 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?.(); } } ui.stop = effect(() => sync(e.target as HTMLDialogElement, open, ui))} onremove={() => { ui.stop?.(); ui.unlock?.(); }} onclose={() => open = false}> ``` `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](../templates/checkbox), [ColorPicker](../templates/color-picker), [Field](../templates/field), [NumberInput](../templates/number-input), [RadioGroup](../templates/radio-group), [Select](../templates/select), [Slider](../templates/slider), [TagsInput](../templates/tags-input), [Toast](../templates/toast), [ToggleGroup](../templates/toggle-group), [Tree](../templates/tree), [VirtualList](../templates/virtual-list). `watchValue` and `untracked`: most templates with a controller, from [Accordion](../templates/accordion) to [Sidebar](../templates/sidebar).