-
Notifications
You must be signed in to change notification settings - Fork 0
Reactivator API: watch()
Parameters: (obj, func)
Returns: For convenience, this function also returns the func
parameter. See Comments section below.
This function installs a watch, which notifies of changes to the obj
parameter supplied. The obj
argument must be a reactivator object, that is, an object which was returned by a previous call to either ref() or reactive().
The following is the function signature for the callback itself:
Parameters: (old, val, prop, name, obj)
None of the parameters are needed if the desire is only to be informed that obj
has changed. Typically, especially in cases where ref() was used, only old
and val
are useful. However, for reactive() objects, in some cases the other parameters may be useful, such as in the case of the detailed console info provided in Example 2 below. So here is a description of all of these parameters:
-
old
is the value prior to the reactive change notification -
val
is the new value -
prop
is the name of the field being changed. For watches on ref() objects, theprop
will always be"value"
, but for watches onreactive()
objects, it will be the name of the object member field being changed. -
name
provides the relative field names, when dealing with changes to sub-fields underobj
, for example the".sub1"
inobj.sub1.field1
. It will appear with the leading'.'
if present, along with any.sub.sub.subfields
. -
obj
is theref
orreactive
object being modified, itself. This will typically not be used, since the watcher tends to know what it is watching. However, where a singlewatch()
is used for several data items, this may be useful.
- NOTE: The parameters on this
watch()
function vary dramatically from Vue'swatch
andwatchEffect
functions. - This function returns the
func
parameter, as a convenience for the caller. This allows anonymous lambda expressions to be captured for later use in an unwatch() call. See the use ofsavedHandler
in the example below. This is also possible with syntax such aswatch(count, savedFunc = (old,val) => {
but in that case thesavedFunc
method would need to be declared previously, without initialization, adding to the burden of this call. That said, both forms remain available for use. - It is also worth noting that the return value and
savedFunc
can be ignored entirely if a call tounwatch
will not be required later.
import { ref, watch, unwatch } from 'reactivator'
let count = ref(42)
count.value++; // this one gets missed, no watch handler yet
let savedHandler = watch(count, (old,val) => {
console.log(`count has changed from ${old} to ${val}`)
})
count.value++; // this one is recorded by the watch above
count.value++; // this one is recorded by the watch above
unwatch(count, savedHandler);
count.value++; // this one gets missed
count has changed from 43 to 44
count has changed from 44 to 45
This example provides more accurate reporting of the changes, through the use of a more complex onStateChange
watch handler function. Also, when it detects the change is an object, it passes a true
to dumpValue
in order to have the value dumped as JSON:
import { reactive, watch, unwatch, dumpValue } from 'reactivator'
let state = reactive({field1: 42, field2: 'hello'})
// Let's define a more complex watch handler for object and array changes
function onStateChange(old, val, prop, name, obj) {
let label = name ? `test3${name}` : 'test3';
if (Array.isArray(obj) && prop === 'length')
console.log(`watch: ${label}.${prop} changed to ${dumpValue(val)}`);
else
if (Array.isArray(obj) && parseInt(prop))
console.log(`watch: ${label}[${prop}] changed from ${dumpValue(old)} to ${dumpValue(val)}: ${dumpValue(obj)}`);
else
if (old !== undefined)
console.log(`watch: ${label}.${prop} changed from ${dumpValue(old)} to ${dumpValue(val)}`);
else
if (Array.isArray(val))
console.log(`watch: ${label}.${prop} assigned a new array ${dumpValue(val)}`);
else
if (typeof val === 'object')
console.log(`watch: ${label}.${prop} assigned a new object: ${dumpValue(val, true)}`);
else
console.log(`watch: ${label}.${prop} assigned value ${dumpValue(val)}`);
}
state.field1 = 99; // no watch installed yet
// Let's define a more complex watch handler for object and array changes
watch(state, onStateChange)
state.field1 = 100;
state.field3 = 'completely new';
state.field2 = 'Goodbye';
state.emptyArray = [ ];
state.newArray = [ 'one', 'two' ];
state.newArray.push('three');
state.sub1 = { sub1a: 'value1a', sub1b: 'value1b' };
state.sub1.sub1b = 'new1b';
unwatch(state, onStateChange); // now uninstall the watch
state.field1 = 101;
watch: state.field1 changed from 99 to 100
watch: state.field3 assigned value 'completely new'
watch: state.field2 changed from 'hello' to 'Goodbye'
watch: state.emptyArray assigned a new array [ ]
watch: state.newArray assigned a new array ['one','two']
watch: state.newArray.2 assigned value 'three'
watch: state.newArray.length changed from 3 to 3
watch: state.sub1 assigned a new object: {"sub1a":"value1a","sub1b":"value1b"}
watch: state.sub1.sub1b changed from 'value1b' to 'new1b'