cref

Copy a structure before deep conversion so the original data remains unchanged.

crefReactivity

Copy a structure before deep conversion so the original data remains unchanged.

Overview

The cref function creates a deep ref from a flattened copy of the given value.

It is equivalent to calling ref(flatten(value)): nested refs are unwrapped into plain values first, then the copied structure is converted into deep refs.

Use cref when you want deep ref behavior without mutating the original object graph during initial conversion.

Try it live

Compare deep, copied, and shallow stateLive API
REF / DEEPAda

Nested properties are refs.

CREF / COPY FIRSTAda

Original still says Ada.

SREF / SHALLOWAda

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

import { cref } from 'regor'

const source = {
  user: {
    name: 'Ada',
  },
}

const state = cref(source)

state().user().name('Grace')

console.log(source.user.name)
// Outputs: Ada

console.log(state().user().name())
// Outputs: Grace

Parameters

  • value (optional): Any value that you want to copy and convert into a deep ref.

Return Value

The cref function returns the same kind of deep ref as ref.

Copy first, then make it reactive

Use cref for plain source data whose original structure should remain intact.

Notes

  • cref(value) is equivalent to ref(flatten(value)).
  • cref does not mutate the original object graph during initial conversion.
  • cref does extra work compared with ref, so use ref for performance-critical paths where in-place conversion is acceptable.
  • cref follows flatten behavior for nested refs, arrays, sets, maps, and circular references.

See Also

Related APIs and guides Continue with the references connected to cref.

Back to the API list