docs icon indicating copy to clipboard operation
docs copied to clipboard

Vague: "If an object is assigned as a ref's value, the object is made deeply reactive with reactive(). "

Open jcalfee opened this issue 2 years ago • 3 comments

Vue version

current

Link to minimal reproduction

ttps://vuejs.org/api/reactivity-core.html#ref

Steps to reproduce

Could you please clarify: "If an object is assigned as a ref's value, the object is made deeply reactive with reactive()."

Does this mean just const obj = ref({deep: {ref: 1}}) or this too obj.value = {deep: {ref: 1}}? I think this should say at a minimum: "If an object is assigned as a ref's value when constructed, the object is made deeply reactive with reactive()." because in my testing, assigning after the fact directly to value does not appear to wrap the properties in a proxy.

https://vuejs.org/api/reactivity-core.html#ref

What is expected?

Docs should cover all cases..

What is actually happening?

Ended up guessing.

System Info

No response

Any additional comments?

Great API and the docs are actually very good.

jcalfee avatar Apr 04 '23 15:04 jcalfee

And should probably show in the example later, an object assigned directly to count.value will notify listeners but is not made deeply reactive.

jcalfee avatar Apr 04 '23 15:04 jcalfee

because in my testing, assigning after the fact directly to value does not appear to wrap the properties in a proxy.

I'm not sure what testing you did, but assigning the value after the fact does wrap the object in a proxy. It is not solely when the ref is constructed.

skirtles-code avatar Apr 04 '23 18:04 skirtles-code

I think the confusion can be explained with following example (just noting down my thoughts and observations, please help me out in case I got anything wrong):

const test = ref({ a: 0 });

// watch the REF (this is NOT deep by default, only reactive objects are watched deeply by default)
watch(test, t => console.log('watch', t.a));

// watch the REF, but deep (reactive properties)
watch(test, t => console.log('watch deep', t.a), { deep: true });

// watch the REACTIVE VALUE (this is deep by default because it is a reactive value)
// BUT if we assign to .value the reactive of this watch is lost
watch(test.value, t => console.log('watch value', t.a));

// First we change a property on the reactive object, which triggers watchers on:
// - The reactive object
// - The ref if using { deep: true }
setTimeout(() => {
  console.log('update 1');
  test.value.a = 1;
}, 2000);

// Second change the value of the ref. THIS REPLACES THE REACTIVE OBJECT WITH A NEW (ALSO REACTIVE) ONE.
// Triggers the watchers on:
// - The ref
// - The ref if using { deep: true }
setTimeout(() => {
  console.log('update 2');
  test.value = { a: 2 };
}, 4000);

// Third change the property on the NEW reactive object, which triggers watchers on:
// - The NEW reactive object
// - The ref if using { deep: true }
setTimeout(() => {
  console.log('update 3');
  test.value.a = 3;
}, 6000);

// Fourth change the value of the ref again. We are replacing the reactive object again.
// This triggers the watchers on:
// - The ref
// - The ref if using { deep: true }
setTimeout(() => {
  console.log('update 4');
  test.value = { a: 4 };
}, 6000);

I get the following output in the browser:

image

I'm not really sure if there is a better way to explain this in the docs?

Valandur avatar Apr 18 '23 21:04 Valandur