--- category: Reactivity alias: controlledRef related: computedWithControl --- # refWithControl Fine-grained controls over ref and its reactivity. ## Usage `refWithControl` uses `extendRef` to provide two extra functions `get` and `set` to have better control over when it should track/trigger the reactivity. ```ts import { refWithControl } from '@vueuse/core' const num = refWithControl(0) const doubled = computed(() => num.value * 2) // just like normal ref num.value = 42 console.log(num.value) // 42 console.log(doubled.value) // 84 // set value without triggering the reactivity num.set(30, false) console.log(num.value) // 30 console.log(doubled.value) // 84 (doesn't update) // get value without tracking the reactivity watchEffect(() => { console.log(num.peek()) }) // 30 num.value = 50 // watch effect wouldn't be triggered since it collected nothing. console.log(doubled.value) // 100 (updated again since it's a reactive set) ``` ### `peek`, `lay`, `untrackedGet`, `silentSet` We also provide some shorthands for doing the get/set without track/triggering the reactivity system. The following lines are equivalent. ```ts import { refWithControl } from '@vueuse/core' // ---cut--- const foo = refWithControl('foo') ``` ```ts import { refWithControl } from '@vueuse/core' const foo = refWithControl('foo') // ---cut--- // getting foo.get(false) foo.untrackedGet() foo.peek() // an alias for `untrackedGet` ``` ```ts import { refWithControl } from '@vueuse/core' const foo = refWithControl('foo') // ---cut--- // setting foo.set('bar', false) foo.silentSet('bar') foo.lay('bar') // an alias for `silentSet` ``` ## Configurations ### `onBeforeChange()` `onBeforeChange` option is offered to give control over if a new value should be accepted. For example: ```ts import { refWithControl } from '@vueuse/core' // ---cut--- const num = refWithControl(0, { onBeforeChange(value, oldValue) { // disallow changes larger then ±5 in one operation if (Math.abs(value - oldValue) > 5) return false // returning `false` to dismiss the change }, }) num.value += 1 console.log(num.value) // 1 num.value += 6 console.log(num.value) // 1 (change been dismissed) ``` ### `onChanged()` `onChanged` option offers a similar functionally as Vue's `watch` but being synchronized with less overhead compared to `watch`. ```ts import { refWithControl } from '@vueuse/core' // ---cut--- const num = refWithControl(0, { onChanged(value, oldValue) { console.log(value) }, }) ``` ## Type Declarations ```ts export interface ControlledRefOptions { /** * Callback function before the ref changing. * * Returning `false` to dismiss the change. */ onBeforeChange?: (value: T, oldValue: T) => void | boolean /** * Callback function after the ref changed * * This happens synchronously, with less overhead compare to `watch` */ onChanged?: (value: T, oldValue: T) => void } /** * Fine-grained controls over ref and its reactivity. * * @__NO_SIDE_EFFECTS__ */ export declare function refWithControl( initial: T, options?: ControlledRefOptions, ): ShallowUnwrapRef<{ get: (tracking?: boolean) => T set: (value: T, triggering?: boolean) => void untrackedGet: () => T silentSet: (v: T) => void peek: () => T lay: (v: T) => void }> & Ref /** @deprecated use `refWithControl` instead */ export declare const controlledRef: typeof refWithControl ```