sref
Hold shallow writable state and replace plain object values to notify bindings.
Hold shallow writable state and replace plain object values to notify bindings.
Overview
The sref function converts a given value into an sref (short for "simple ref") object and returns the sref. An sref allows you to both retrieve and update its value.
The nested properties of an sref are not converted to refs.
Try it live
Nested properties are refs.
Original still says Ada.
Replace the plain object to notify.
- isRef(deep) / isDeepRef(deep)
- true / true
- isDeepRef(shallow) / unref(name)
- false / Ada
{
"profile": {
"name": "Ada"
}
} import {
computed,
cref,
flatten,
html,
isDeepRef,
isRef,
ref,
sref,
unref,
} from 'regor'
export function createState(interactive = false) {
const original = { profile: { name: 'Ada' } }
const deep = ref({ profile: { name: 'Ada' } })
const copied = cref(original)
const shallow = sref({ profile: { name: 'Ada' } })
const name = ref('Grace')
const apply = () => {
deep().profile().name(name())
copied().profile().name(name())
shallow({ profile: { name: name() } })
}
return {
interactive,
name,
deep,
copied,
shallow,
apply,
originalName: original.profile.name,
snapshot: computed(() => JSON.stringify(flatten(deep()), null, 2)),
refCheck: isRef(deep),
deepCheck: isDeepRef(deep),
shallowCheck: isDeepRef(shallow),
plainName: computed(() => unref(deep().profile().name)),
}
}
export const stateTemplate = html` <div class="guide-demo">
<div class="guide-filter">
<label
>New name<input
type="text"
maxlength="30"
r-model="name"
:value="name"
:disabled="!interactive" /></label
><button type="button" @click="apply" :disabled="!interactive">
Apply to all three
</button>
</div>
<div class="api-comparison">
<article class="directive-card">
<span class="guide-kicker">REF / DEEP</span
><strong>{{ deep.profile.name }}</strong>
<p>Nested properties are refs.</p>
</article>
<article class="directive-card">
<span class="guide-kicker">CREF / COPY FIRST</span
><strong>{{ copied.profile.name }}</strong>
<p>Original still says {{ originalName }}.</p>
</article>
<article class="directive-card">
<span class="guide-kicker">SREF / SHALLOW</span
><strong>{{ shallow.profile.name }}</strong>
<p>Replace the plain object to notify.</p>
</article>
</div>
<dl class="directive-values">
<div>
<dt>isRef(deep) / isDeepRef(deep)</dt>
<dd>{{ refCheck }} / {{ deepCheck }}</dd>
</div>
<div>
<dt>isDeepRef(shallow) / unref(name)</dt>
<dd>{{ shallowCheck }} / {{ plainName }}</dd>
</div>
</dl>
<pre class="api-snapshot" r-text="snapshot"></pre>
</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 name and apply it. Inspect the nested values, ref checks, and flattened snapshot.
Usage
Getting the SRef Value
You can access the value of the sref object using two methods:
srefObj.value: Accesses the value directly.srefObj(): Invokes the sref object to retrieve its value.
Setting the SRef Value
To update the value of an sref object, you have two options:
srefObj.value = newValue: Sets the value directly.srefObj(newValue): Invokes the sref object with the new value to update it.
Parameters
-
value(optional): Any value that you want to convert into an sref object. The function supports several input types:- Basic types such as numbers, strings, booleans, Date etc.
- sref objects.
- objects
- Array, Map, Set.
nullorundefined.
Return Value
The sref function returns an sref object representing the input value. The specific type of the returned sref object depends on the input value's type.
For ordinary objects, mutating a nested field does not notify by itself. Replace the object or trigger intentionally.
Notes
-
srefmodifies prototype of arrays, maps, and sets to make them reactive. -
Observers can be attached to the sref object to be notified of changes to its value.
-
The function also supports batch collecting changes and pausing/resuming auto-triggering of observers.
-
Every
refis ansref, but not everysrefis aref.
Example
import { sref } from 'regor'
const initialValue = {
name: 'John',
age: 30,
hobbies: ['reading', 'swimming'],
}
const mySRef = sref(initialValue)
// Accessing the sref value using function call
console.log(mySRef()) // Outputs the initial value
// Accessing the sref value using value getter
console.log(mySRef.value) // Outputs the initial value
// Updating the sref value
mySRef().name = 'Alice' // Directly modifying the sref value
console.log(mySRef().name) // Outputs 'Alice'
mySRef({
name: 'Alice',
age: 35,
hobbies: ['reading', 'swimming'],
}) // Invoking the sref with a new value
console.log(mySRef().age) // Outputs 35