I created a reactive object and after adding a new prop to it in a @click event handler it doesn't seem to be reactive and doesn't update it in the template.
However, if I add a new property in the setup method it works.
Here's the full code:
<template>
<div id="app">
<pre>{{dynamicObj}}</pre>
<button @click="onButtonClick">Add prop3</button>
</div>
</template>
<script>
import { reactive } from "@vue/composition-api";
export default {
name: "App",
setup() {
const dynamicObj = reactive({
prop1: "prop1"
});
function onButtonClick() {
dynamicObj.prop3 = "prop3";
console.log(dynamicObj);
}
dynamicObj.prop2 = "prop2";
return {
dynamicObj,
onButtonClick
};
}
};
</script>
and here you can play with the code.
Expected result after clicking the button:
{
"prop1": "prop1",
"prop2": "prop2",
"prop3": "prop3",
}
result:
{
"prop1": "prop1",
"prop2": "prop2"
}
https://vuejs.org/v2/guide/reactivity.html#For-Objects
Compoisition API plugin is not Vue 3 and have same caveats as Vue 2
ah got it, I thought the plugin would handle that, but I understand that it's not possible due to the way Vue 2 works, thank you very much for clarifying
ok, I'll reopen this issue just to ask if there is a way of adding an existing ref to an existing reactive object. I tried it here using Vue.set() but the result is:
{
"prop1": "prop1",
"prop2": "prop2",
"prop3": {
"value": "prop3"
}
}
ok, I'll reopen this issue just to ask if there is a way of adding an existing
refto an existingreactiveobject. I tried it here usingVue.set()but the result is:{ "prop1": "prop1", "prop2": "prop2", "prop3": { "value": "prop3" } }
Hi oswaldofreitas,
Try changing Vue.set() to the following. The only downside I can think of is that prop3 is going to behave as a ref, thus the need for .value when using it in setup(). Dynamically adding a ref like this could also cause some unwanted side effects, but I haven't tested anything other than modifying your example with the below change.
Vue.set(dynamicObj, "prop3", prop3.value);
Edit:
I played around a bit more and you can see that dynamicObj.prop3 is not reactive when added in this way. It is reactive in the sense that it will update when clicking the button, but only after clicking. See this codesandbox
The following also gives interesting results in place of Vue.set() mentioned above:
dynamicObj = reactive(Object.assign({}, dynamicObj, { prop3: prop3.value }));
thanks @ShaggyTech but yeah, I got at the same conclusion as you when I tried passing the .value as it loses the reference to the original variable.
using the plugin's own set() method (which adds a bit additional magic for unwrapping refs) and a computed prop makes it work the way you want, I think.
import Vue from "vue";
import { reactive, ref, set, computed } from "@vue/composition-api";
export default {
name: "App",
setup() {
let dynamicObj = reactive({
prop1: "prop1"
});
const prop3 = ref("prop3");
function onButtonClick() {
set(dynamicObj, "prop3", computed(() => prop3.value));
console.log(dynamicObj);
}
dynamicObj.prop2 = "prop2";
return {
prop3,
dynamicObj,
onButtonClick
};
}
};
super nice @LinusBorg, thank you!
Most helpful comment
using the plugin's own
set()method (which adds a bit additional magic for unwrapping refs) and a computed prop makes it work the way you want, I think.