Reputation: 612
I'm using Vue's Composition API. When I write some code that adds a property to a ref
object, the template renderer does not seem to detect the change. Here is my code:
<template>
<div id="app">
<button @click="updateObj">Click</button>
<div v-if="obj[1]">{{ obj[1] }}</div>
</div>
</template>
<script>
import { defineComponent, ref } from "@vue/composition-api";
export default defineComponent({
name: "App",
setup() {
const obj = ref({});
const updateObj = () => {
obj.value[1] = "hello";
console.log(obj.value);
};
return {
obj,
updateObj,
};
},
});
</script>
Clicking on the button calls updateObj
which then sets the property "1" on obj
to "hello". If obj[1]
is set, you should see "hello" in the browser, but nothing is displayed. Here's a codepen to the demo.
I've been using the Composition API for months now and feel like I've gotten the hang of it, but I have no idea what's going on here. I've also tried reactive
instead of ref
but still no luck.
Upvotes: 2
Views: 3306
Reputation: 121
I'm adding my answer here so when I google this again in six months I'll find it.
If you are using composition api with Vue 2, you need to use set to add a new tracked property to an object.
From https://github.com/vuejs/composition-api
⚠️ set and del workaround for adding and deleting reactive properties ⚠️ Warning: set and del do NOT exist in Vue 3. We provide them as a workaround here, due to the limitation of Vue 2.x reactivity system.
In Vue 2, you will need to call set to track new keys on an object(similar to Vue.set but for reactive objects created by the Composition API). In Vue 3, you can just assign them like normal objects.
Similarly, in Vue 2 you will need to call del to ensure a key deletion triggers view updates in reactive objects (similar to Vue.delete but for reactive objects created by the Composition API). In Vue 3 you can just delete them by calling delete foo.bar.
<template>
<div id="app">
<button @click="updateObj">Click</button>
<div v-if="obj[1]">{{ obj[1] }}</div>
</div>
</template>
<script>
import { defineComponent, ref, set } from "@vue/composition-api";
export default defineComponent({
name: "App",
setup() {
const obj = ref({});
const updateObj = () => {
set(obj.value, 1, "hello");
console.log(obj.value);
};
return {
obj,
updateObj,
};
},
});
</script>
Upvotes: 2
Reputation: 1
You should use ref
when you work with primitive values, if you want to use an object you have to use reactive
, in the official docs they say :
If using ref, we are largely translating style (1) to a more verbose equivalent using refs (in order to make the primitive values reactive).
- Using reactive is nearly identical to style (2). We only need to create the object with reactive and that's it.
- Using reactive is nearly identical to style (2). We only need to create the object with reactive and that's it.
...
Use ref and reactive just like how you'd declare primitive type variables and object variables in normal JavaScript. It is recommended to use a type system with IDE support when using this style.
To make it reactive assign the object directly to the ref's value :
obj.value = { 1: "hello" };
Upvotes: 2