davestewart / vuex-pathify

Vue / Vuex plugin providing a unified path syntax to Vuex stores
https://davestewart.github.io/vuex-pathify
MIT License
1.37k stars 57 forks source link

'get()' helper can modify subproperties? #87

Closed bkarlson closed 4 years ago

bkarlson commented 4 years ago

I just discovered that one of my older components (when Pathify was still a mystery to me) can modify subproperties of a computed property that users Pathify's get() helper:

  computed: {
    ...get('uiStore/', ['uiSettings'])
},

In my template this works fine:

<li @click="uiSettings.darkMode = !uiSettings.darkMode">

Yet i'd expect since it's get() rather than sync() Vue should throw a "no setter" error, no?

davestewart commented 4 years ago

Should do.

This is the function that the helper will return:

If you can post a demo showing this, that would be useful.

bkarlson commented 4 years ago

Here's an example:

https://codesandbox.io/s/vue-template-iztvw?from-embed

Subproperty of an object "getted" by Pathify can be modified, but subproperty that was itself "getted" by pathify requires a setter (expected).

davestewart commented 4 years ago

Hey, had time to take a look at this.

This behaviour is expected because of JavaScript's "by-reference" passing of objects. Not sure if you are familiar with this; if not, Google it, or I can explain.

In this fork of your demo...

  computed: get('ui', [
    'obj',
    'obj@sub',
  ]),

...I have set Vuex's "strict" mode to true and you will see an error is thrown when you modify a property (or sub-property) without going through a commit; in this case via obj.sub:

If you attempt to set sub the you also get an error, because the helper only returned a getter function.

So to get and set @sub, use sync which will set up a commit() for you. Just make sure you have created the mutations using make.mutation() which will set up a special mutation on obj which will detect the special Pathify Payload class passed by computed properties triggered by Pathify's sync and pass along path information so that the obj mutation can modify its own sub-property.

Sorry if that sound complicated; it's the nature of Vuex that only top-level properties are designed to be changed, and where Pathify's value / magic comes in to do this sub-property mutation.

Closing as it's just how JavaScript / Vuex works.

Hope that helps! Glad you are digging in and finding out anyway :)

bkarlson commented 4 years ago

very helpful indeed, thanks for the explanation!