watchEffect
Run an effect immediately, then rerun it when the refs it reads change.
Run an effect immediately, then rerun it when the refs it reads change.
Overview
The watchEffect function allows you to create an "effect" that automatically reacts to changes in reactive data, such as ref objects or other observables. This effect is useful for handling side effects, such as updating the UI, in a reactive and efficient manner.
Try it live
Current refs: 1 / 10
Last effect: 1 + 10 = 11
The silenced read does not rerun the effect. collectRefs captures one dependency and returns the sampled sum: 11.
import { collectRefs, html, ref, silence, watchEffect } from 'regor'
export function createEffects(interactive = false) {
const tracked = ref(1),
untracked = ref(10)
const runs = ref(0),
cleanups = ref(0),
result = ref('')
const collected = ref(0),
inspected = ref(0)
watchEffect((onCleanup) => {
const value = tracked()
silence(() => {
runs(runs() + 1)
result(`${value} + ${untracked()} = ${value + untracked()}`)
})
onCleanup?.(() => silence(() => cleanups(cleanups() + 1)))
})
const inspect = () => {
const read = collectRefs(() => tracked() + silence(() => untracked()))
collected(read.refs.length)
inspected(read.value)
}
inspect()
return {
interactive,
tracked,
untracked,
runs,
cleanups,
result,
collected,
inspected,
inspect,
bumpTracked: () => tracked(tracked() + 1),
bumpUntracked: () => untracked(untracked() + 1),
}
}
export const effectsTemplate = html` <div class="guide-demo">
<div class="guide-session-bar">
<button type="button" @click="bumpTracked" :disabled="!interactive">
Update tracked</button
><button type="button" @click="bumpUntracked" :disabled="!interactive">
Update silenced read</button
><button type="button" @click="inspect" :disabled="!interactive">
Collect the reads
</button>
</div>
<p>Current refs: <strong>{{ tracked }} / {{ untracked }}</strong></p>
<p class="guide-event">Last effect: {{ result }}</p>
<div class="guide-metrics">
<div><output>{{ runs }}</output><span>Effect runs</span></div>
<div><output>{{ cleanups }}</output><span>Effect cleanups</span></div>
<div>
<output>{{ collected }}</output><span>Collected dependencies</span>
</div>
</div>
<p class="guide-hint">
The silenced read does not rerun the effect. collectRefs captures one
dependency and returns the sampled sum: {{ inspected }}.
</p>
</div>` import { createApp, RegorConfig, useScope } from 'regor'
import { apiExamples } from './examples'
const element = document.getElementById('api-demo')
const name = element?.dataset.example
if (element && name && Object.hasOwn(apiExamples, name)) {
const example = apiExamples[name as keyof typeof apiExamples]
const scope = useScope<object>(() => example.create(true))
const config =
'config' in scope.context && scope.context.config instanceof RegorConfig
? scope.context.config
: undefined
createApp(scope, { element, template: example.template }, config)
} Change the tracked and silenced values separately. Collect the reads to inspect the dependency count and returned result.
Usage
Creating Effects
To create an effect using watchEffect, you provide a function that defines the effect. This function will be called immediately and then re-called whenever the reactive data it depends on changes.
import { watchEffect, ref } from 'regor'
const myRef = ref('Hello, Regor!')
// Create a watch effect
const stopWatching = watchEffect(() => {
console.log('Value:', myRef.value)
})
// Later, when the effect is no longer needed, stop it
stopWatching() Parameters
effect: A function that defines the effect you want to create. This function may optionally receive a callback function (onCleanup) as an argument.
Return Value
- The
watchEffectfunction returns astopWatchingfunction that allows you to stop the effect when it's no longer needed. CallingstopWatchingwill unsubscribe the effect from the reactive data.
Example
import { watchEffect, ref } from 'regor'
const myRef = ref('Hello, Regor!')
// Create a watch effect that updates the UI
const stopWatching = watchEffect(() => {
console.log('Value:', myRef.value)
})
// Later, when the effect is no longer needed, stop it
stopWatching() Keep unrelated reads outside the effect or wrap them with silence. Use the cleanup callback for resources from an effect run.