0
votes

I have a question about how Vuex reactivity is designed to work. I have the following store:

// state
state: {
    database: {
        tables: []
    }
}

// mutator
ADD_TABLE(state, {table}) {
    state.database.tables.push(table);
}

So when the ADD_TABLE mutation happens vue components and the vuex watch react only when the object is directly changed and not reacting on nested property change.

// after the mutation happens
store.watch(state => state.database, change => console.log(change)) // this doesn't log
store.watch(state => state.database.tables, change => console.log(change)) // this does

Is this the desired behavior and why, or I have something breaking in my code?

1
Could you try adding { deep: true } as the third argument to your watcher and see if that works.Stephan-v
Yep, that does work but still, I added the watchers for a quick explanation here on SO. In the actual code its binded in the data / computed properties and the component doesn't react to the change.korun
That's just how watchers work in Vue. If you watch a particular property, the default in Vue is a shallow watch. You need to specify a deep watch if you want to watch everything. Could you provide an example of the actual problem that specifying deep doesn't solve?Bert

1 Answers

1
votes

This is intended as a performance optimisation in Vue.js, similarly as PureComponents work in React for example.

By default only shallow comparison is done, meaning that only reference to the object property is checked.

Change will be picked up if database property is renamed, removed or another property is added to the object, indicating a change in the first level of the object.

You can mitigate this by adding deep or optimising properties that you pass on.

For example if your db object would only have a single child property, it could easily be changed to something like

state: {
    databaseTables: []
}