Subscribe on changes!

Reactive does not work on data getter

avatar
Sep 12th 2021

Version

3.2.11

Reproduction link

codepen.io/hqnan/pen/MWomNaJ

Steps to reproduce

Open link

What is expected?

Vue render hi, 1

What is actually happening?

Vue is rendering hi, null


I have data like this:

const form = {
    value: null,
    props: {
       get test() {
          return `hi, ${form.value}`;
        }
    }
}

The form.props.test property is a getter and is using the form.value.

In template, I render: {{ form.props.test }}.

In the mounted hook, I do form.props.test = 1. What is expected here is the template should render: hi, 1

This issue does not occur in Vue 2: https://codepen.io/hqnan/pen/GREmVqa

avatar
Sep 12th 2021

Vue 3 uses proxies for reactivity, where changes made directly to the original object are not observed.

You have a hard reference to the original, non-reactive plain form object in the getter, so reading the getter will not result in registering form as a reactive dependency - because it's a plain object.

Working version:

import { ref, reactive } from "vue";

export default {
  data() {
    const form = reactive({
      value: null,
      props: {
        get test() {
          return `hi, ${form.value}`;
        }
      }
    });
    return {
      form
    };
  },

Note that this would not be the case if your getter used this in reference to the object the getter is defined in - that would be reactive.

I'll close this as there's no way to cover this automatically, you have to use reactive() here explicitly.

avatar
Sep 13th 2021

Thanks, @LinusBorg 💕

But how can I use this in a nested object?

{
      value: null,
      props: {
        get test() {
          return `hi, ${this.value}`;
        }
     }
}

this.value will be undefined

avatar
Sep 13th 2021

You can't, that's not what I meant.

In my experience, getters are just often used to refer to the same object they are defined on - and I wanted to make clear that in this common scenario, where you can use this, it just works.

avatar
Sep 14th 2021

thanks a lot, @LinusBorg ❤️

I'm developing a Vue.js library and was struggling with the new reactivity system of Vue 3, I thought it can be resolved natively without import anything, but I'm ok with importing reactive from Vue 3.