new·The score now tells you which way it movedA brain's exam only ever grows: its own material writes questions, and so does every question a real caller asked and did not get answered. The score is a percentage over that growing set, so a brain that learned more could post a smaller number — and this week three did. One of them answered two MORE questions than the week before and showed eighteen points less. Printed as a single percentage, that reads as decline to a reader and as punishment to anyone who contributes material.all news →
mozg.beta
Sign in

Vue · all subjects

reactivity: core apis

38 notes, read out of this brain and free to use. Each one was extracted from a source and is re-checked against its exam.

ref() creates a reactive mutable ref object

ref() takes an inner value and returns a reactive and mutable ref object with a single property .value that points to the inner value. The ref object is mutable (you can assign new values to .value) and reactive (read operations are tracked, write operations trigger effects). If an object is assigned as a ref's value, the object is made deeply reactive with reactive(). If the object contains nested refs, they will be deeply unwrapped. To avoid deep conversion, use shallowRef() instead.

ref() function signature and Ref interface

function ref<T>(value: T): Ref<UnwrapRef<T>> interface Ref<T> { value: T }

ref() example usage

const count = ref(0) console.log(count.value) // 0 count.value = 1 console.log(count.value) // 1

reactive() returns a reactive proxy of an object

reactive() returns a reactive proxy of the object. The reactive conversion is deep: it affects all nested properties. A reactive object also deeply unwraps any properties that are refs while maintaining reactivity. There is no ref unwrapping performed when the ref is accessed as an element of a reactive array or a native collection type like Map. To avoid deep conversion and only retain reactivity at the root level, use shallowReactive() instead. The returned object and its nested objects are wrapped with ES Proxy and are not equal to the original objects. It is recommended to work exclusively with the reactive proxy and avoid relying on the original object.

reactive() function signature

function reactive<T extends object>(target: T): UnwrapNestedRefs<T>

reactive() creating reactive object example

const obj = reactive({ count: 0 }) obj.count++

reactive() ref unwrapping example

const count = ref(1) const obj = reactive({ count }) // ref will be unwrapped console.log(obj.count === count.value) // true // it will update `obj.count` count.value++ console.log(count.value) // 2 console.log(obj.count) // 2 // it will also update `count` ref obj.count++ console.log(obj.count) // 3 console.log(count.value) // 3

reactive() refs not unwrapped in arrays or collections

Refs are not unwrapped when accessed as array or collection elements. You must use .value to access the ref's value in these cases. const books = reactive([ref('Vue 3 Guide')]) // need .value here console.log(books[0].value) const map = reactive(new Map([['count', ref(0)]])) // need .value here console.log(map.get('count').value)

reactive() ref assigned to reactive property is unwrapped

When assigning a ref to a reactive property, that ref will be automatically unwrapped. const count = ref(1) const obj = reactive({}) obj.count = count console.log(obj.count) // 1 console.log(obj.count === count.value) // true

readonly() creates a readonly proxy

readonly() takes an object (reactive or plain) or a ref and returns a readonly proxy to the original. A readonly proxy is deep: any nested property accessed will be readonly as well. It has the same ref-unwrapping behavior as reactive(), except the unwrapped values will also be made readonly. To avoid deep conversion, use shallowReadonly() instead.

readonly() function signature

function readonly<T extends object>( target: T ): DeepReadonly<UnwrapNestedRefs<T>>

readonly() example usage

const original = reactive({ count: 0 }) const copy = readonly(original) watchEffect(() => { // works for reactivity tracking console.log(copy.count) }) // mutating original will trigger watchers relying on the copy original.count++ // mutating the copy will fail and result in a warning copy.count++ // warning!

watchEffect() runs function immediately and reactively tracks dependencies

watchEffect() runs a function immediately while reactively tracking its dependencies and re-runs it whenever the dependencies change. The first argument is the effect function to be run. The effect function receives a function that can be used to register a cleanup callback. The cleanup callback will be called right before the next time the effect is re-run, and can be used to clean up invalidated side effects, e.g. a pending async request. The second argument is an optional options object that can be used to adjust the effect's flush timing or to debug the effect's dependencies. By default, watchers will run just prior to component rendering. The return value is a handle function that can be called to stop the effect from running again.

watchEffect() function signature

function watchEffect( effect: (onCleanup: OnCleanup) => void, options?: WatchEffectOptions ): WatchHandle type OnCleanup = (cleanupFn: () => void) => void interface WatchEffectOptions { flush?: 'pre' | 'post' | 'sync' // default: 'pre' onTrack?: (event: DebuggerEvent) => void onTrigger?: (event: DebuggerEvent) => void } interface WatchHandle { (): void // callable, same as `stop` pause: () => void resume: () => void stop: () => void }

watchEffect() flush timing options

By default, watchers will run just prior to component rendering (flush: 'pre'). Setting flush: 'post' will defer the watcher until after component rendering. Setting flush: 'sync' will trigger a watcher immediately when a reactive dependency changes, but should be used with caution as it can lead to problems with performance and data consistency if multiple properties are being updated at the same time.

watchEffect() basic example

const count = ref(0) watchEffect(() => console.log(count.value)) // -> logs 0 count.value++ // -> logs 1

watchEffect() stopping example

const stop = watchEffect(() => {}) // when the watcher is no longer needed: stop()

watchEffect() options example

watchEffect(() => {}, { flush: 'post', onTrack(e) { debugger }, onTrigger(e) { debugger } })

watchPostEffect() alias

watchPostEffect() is an alias of watchEffect() with flush: 'post' option.

watchSyncEffect() alias

watchSyncEffect() is an alias of watchEffect() with flush: 'sync' option.

watch() observes reactive data sources and invokes callback

watch() watches one or more reactive data sources and invokes a callback function when the sources change. watch() is lazy by default - the callback is only called when the watched source has changed. The first argument is the watcher's source. The second argument is the callback that will be called when the source changes. The callback receives three arguments: the new value, the old value, and a function for registering a side effect cleanup callback. The third optional argument is an options object.

watch() multiple sources function signature

function watch<T>( sources: WatchSource<T>[], callback: WatchCallback<T[]>, options?: WatchOptions ): WatchHandle

watch() type definitions

type WatchCallback<T> = ( value: T, oldValue: T, onCleanup: (cleanupFn: () => void) => void ) => void type WatchSource<T> = | Ref<T> // ref | (() => T) // getter | (T extends object ? T : never) // reactive object interface WatchOptions extends WatchEffectOptions { immediate?: boolean // default: false deep?: boolean | number // default: false flush?: 'pre' | 'post' | 'sync' // default: 'pre' onTrack?: (event: DebuggerEvent) => void onTrigger?: (event: DebuggerEvent) => void once?: boolean // default: false (3.4+) } interface WatchHandle { (): void // callable, same as `stop` pause: () => void resume: () => void stop: () => void }

watch() options: immediate, deep, flush, onTrack, onTrigger, once

immediate: trigger the callback immediately on watcher creation. Old value will be undefined on the first call. Default: false. deep: force deep traversal of the source if it is an object, so that the callback fires on deep mutations. In 3.5+, this can also be a number indicating the max traversal depth. Default: false. flush: adjust the callback's flush timing. Options are 'pre' (default), 'post', or 'sync'. onTrack / onTrigger: debug the watcher's dependencies. Receive DebuggerEvent. once: (3.4+) run the callback only once. The watcher is automatically stopped after the first callback run. Default: false.

watch() advantages over watchEffect()

Compared to watchEffect(), watch() allows us to: perform the side effect lazily, be more specific about what state should trigger the watcher to re-run, and access both the previous and current value of the watched state.

watch() watching a getter example

const state = reactive({ count: 0 }) watch( () => state.count, (count, prevCount) => { /* ... */ } )

watch() watching a ref example

const count = ref(0) watch(count, (count, prevCount) => { /* ... */ })

watch() watching multiple sources example

watch([fooRef, barRef], ([foo, bar], [prevFoo, prevBar]) => { /* ... */ })

watch() deep mode with getter example

const state = reactive({ count: 0 }) watch( () => state, (newValue, oldValue) => { // newValue === oldValue }, { deep: true } )

watch() directly watching reactive object

When directly watching a reactive object, the watcher is automatically in deep mode. const state = reactive({ count: 0 }) watch(state, () => { /* triggers on deep mutation to state */ })

watch() with flush and debugging options example

watch(source, callback, { flush: 'post', onTrack(e) { debugger }, onTrigger(e) { debugger } })

watch() stopping example

const stop = watch(source, callback) // when the watcher is no longer needed: stop()

watch() pausing and resuming example

const { stop, pause, resume } = watch(() => {}) // temporarily pause the watcher pause() // resume later resume() // stop stop()

watch() side effect cleanup example

watch(id, async (newId, oldId, onCleanup) => { const { response, cancel } = doAsyncWork(newId) // `cancel` will be called if `id` changes, cancelling // the previous request if it hasn't completed yet onCleanup(cancel) data.value = await response })

watch() side effect cleanup in 3.5+ example

import { onWatcherCleanup } from 'vue' watch(id, async (newId) => { const { response, cancel } = doAsyncWork(newId) onWatcherCleanup(cancel) data.value = await response })

onWatcherCleanup() registers cleanup function for watcher

onWatcherCleanup() registers a cleanup function to be executed when the current watcher is about to re-run. Can only be called during the synchronous execution of a watchEffect effect function or watch callback function (i.e. it cannot be called after an await statement in an async function). This is available in Vue 3.5+.

onWatcherCleanup() function signature

function onWatcherCleanup( cleanupFn: () => void, failSilently?: boolean ): void

onWatcherCleanup() example usage

import { watch, onWatcherCleanup } from 'vue' watch(id, (newId) => { const { response, cancel } = doAsyncWork(newId) // `cancel` will be called if `id` changes, cancelling // the previous request if it hasn't completed yet onWatcherCleanup(cancel) })

Give your agent this brain