Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

VueJS: unable to update a component property from inside a watcher

I am building a Vue 2 Webpack application that uses Vuex. I am trying to update a component's local state by watching a computed property which is getting data from the Vuex store. This is what the inside of the <script></script> section of my component looks like:

export default {
    name: 'MyComponent',

    data() {
        return {
            // UI
            modal: {
            classes: {
                'modal__show-modal': false,
            },
            tags: [],
            },
        };
    },

    computed: {
        tagList() {
            return this.$store.getters.tagList;
        },
    },

    watch: {
        tagList: (updatedList) => {
            this.modal.tags = updatedList;
        },
    },
};

As you can see, I have a computed property called tagList which fetches data from the store. I have a watcher that watches tagList so that whenever the store's data changes, I can update modal.tags to the new value.

As per Vue documentation, I can call this.propertyName and update my local component state but when I call this.modal.tags = updatedList;, I get the following error:

[Vue warn]: Error in callback for watcher "tagList": "TypeError: Cannot set property 'tags' of undefined"

Why does this error occur even though it looks no different than what is in Vue.js's documentation?

like image 544
JackH Avatar asked Dec 07 '22 15:12

JackH


1 Answers

Don't use arrow functions.

Change from:

watch: {
    tagList: (updatedList) => {
        this.modal.tags = updatedList;
    },
},

To:

watch: {
    tagList(updatedList) {              // changed this line
        this.modal.tags = updatedList;
    },
},

Vue docs mention this a few times:

Don't use arrow functions on an options property or callback, such as created: () => console.log(this.a) or vm.$watch('a', newValue => this.myMethod()). Since arrow functions are bound to the parent context, this will not be the Vue instance as you'd expect, often resulting in errors such as

Uncaught TypeError: Cannot read property of undefined

or

Uncaught TypeError: this.myMethod is not a function

It is basically a context/scope issue. When using arrow functions, the this does not refer to the Vue instance, but the enclosing context of where the component was declared (probably window).

like image 56
acdcjunior Avatar answered Dec 11 '22 07:12

acdcjunior