watchEffect

Run an effect immediately, then rerun it when the refs it reads change.

watchEffectComputed and Effects

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

See which reads become dependenciesLive API

Current refs: 1 / 10

Last effect: 1 + 10 = 11

1Effect runs
0Effect cleanups
1Collected dependencies

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 watchEffect function returns a stopWatching function that allows you to stop the effect when it's no longer needed. Calling stopWatching will 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()
Track only the reads that should cause a rerun

Keep unrelated reads outside the effect or wrap them with silence. Use the cleanup callback for resources from an effect run.

See Also

Related APIs and guides Continue with the references connected to watchEffect.

Back to the API list