flatten
Unwrap a nested reactive structure into plain values.
Unwrap a nested reactive structure into plain values.
Overview
The flatten function recursively traverses a nested structure, such as an object, array, set, or map, and returns a flattened version of the structure. This means that it removes any nested references and produces a structure containing no 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
Flattening Nested Structures
To flatten a nested structure, simply pass the reference to the flatten function. It will return a new structure with all nested references removed.
import { flatten, ref } from 'regor'
const nestedData = {
name: 'John',
age: ref(30),
hobbies: ['reading', 'swimming', ref('drawing')],
}
const flattenedData = flatten(nestedData)
console.log(flattenedData)
// Outputs: { name: 'John', age: 30, hobbies: [ 'reading', 'swimming', 'drawing' ] } Parameters
reference: The nested structure (object, array, set, map) that you want to flatten. It can contain nested refs, which will be resolved during flattening.
Return Value
- The
flattenfunction returns a new structure that is a flattened version of the inputreference. Any nested refs within the structure are resolved, resulting in a single-level structure.
Use a plain snapshot for serialization or external code that should not receive refs.
Notes
-
The
flattenfunction recursively flattens nested structures, including arrays, sets, maps, and objects. -
If the input
referencecontains refs, they are automatically unrefed during flattening, and their values are included in the flattened structure. -
Circular references within the input
referenceare not supported, and attempting to flatten such structures may result in unexpected behavior.
Example
import { flatten, ref } from 'regor'
const nestedData = {
name: 'John',
age: ref(30),
hobbies: ['reading', 'swimming', ref('drawing')],
}
const flattenedData = flatten(nestedData)
console.log(flattenedData)
// Outputs: { name: 'John', age: 30, hobbies: [ 'reading', 'swimming', 'drawing' ] }