shallowRef as prop loses reactivity
Vue version
3.2.37
Link to minimal reproduction
Steps to reproduce
- Create a shallowRef with object value
- Pass the ref as a component prop.
- Print the value of the prop in the template.
- Update a ref object value property.
- Call triggerRef on the created ref.
What is expected?
It is expected that the changes will also be sent to the component without reassigning the value property of the ref
What is actually happening?
Changes are not reflected in the component receiving the ref via prop.
System Info
System:
OS: Linux 5.15 Manjaro Linux
CPU: (16) x64 AMD Ryzen 7 5700G with Radeon Graphics
Memory: 4.24 GB / 13.45 GB
Container: Yes
Shell: 5.9 - /usr/bin/zsh
Binaries:
Node: 14.19.3 - ~/.nvm/versions/node/v14.19.3/bin/node
Yarn: 1.22.19 - ~/.yarn/bin/yarn
npm: 6.14.17 - ~/.nvm/versions/node/v14.19.3/bin/npm
Browsers:
Brave Browser: 103.1.40.107
Chromium: 103.0.5060.114
Firefox: 102.0
Any additional comments?
I'm creating components to work with large amounts of data and I need to manually control when a ref should be triggered to have better performance.
the content of the shallow ref is non-reactive. You pass the content to the child. So you pass a non-reactive content to the child. so you can't watch that object.
@LinusBorg I'm running into this issue and your comment is somewhat confusing, could you clarify how the following point works:
let ganttBars = shallowRef<GanttEntry[]>([]);
ganttBars.value = [...ganttBars.value]; // Does trigger component->watch(data)
triggerRef(ganttBars) // Does not trigger component->watch(data)
<template>
<Timeline :data="ganttBars"/>
</template>
Why does a root mutation trigger watch (or a re-render) while triggerRef
does not? (vue@^3.2.45 btw)
Am I misunderstanding what triggerRef does?
triggerRef
will make the parent re-render, but since the ref still contains the same plain array, no prop has changed for <Timeline>
, so that component will not re-render.
Ah I see that makes sense (properties are compared by using standard js cmp I guess), thank you for the quick clarification
@LinusBorg I'm running into this issue and your comment is somewhat confusing, could you clarify how the following point works:
let ganttBars = shallowRef<GanttEntry[]>([]); ganttBars.value = [...ganttBars.value]; // Does trigger component->watch(data) triggerRef(ganttBars) // Does not trigger component->watch(data) <template> <Timeline :data="ganttBars"/> </template>
Why does a root mutation trigger watch (or a re-render) while
triggerRef
does not? (vue@^3.2.45 btw) Am I misunderstanding what triggerRef does?
In the demo customValue.value
is not reactive, the NotShallowRef.value
is reactive. this is the ref
and shallowRef
's different.
playground demo