0
votes

I'm creating a component that updates props with values from local storage. The props are objects with multiple boolean properties (e.g. this.globalStates.repeat = false). Because I have more than one prop to update, I've created a method for any prop provided as an argument:

  mounted(){
    this.loadLocalData(this.globalStates, "states")
    this.loadLocalData(this.globalSettings, "settings")
  },

  methods: {

    loadLocalData(object, localVariable){ // 'object' receives a prop, 'localVariable' must refer to a string in localStorage (localStorage stores strings only).
      const loadedObject = JSON.parse(localStorage.getItem(localVariable)) // Turn localStorage string into JSON object

      if (loadedObject && typeof loadedObject === "object"){

        for (let item in object){ // iterate through the prop and update each property with the one in loadedObject
          object[item] = loadedObject[item] // Why does this work!?
        }
      }
    }
  },

Now this actually works, without errors or warnings. I don't understand why though. Normally when I try to modify a prop directly, Vue throws a warning at me:

[Vue warn]: Avoid mutating a prop directly since the value will be overwritten whenever the parent component re-renders.

Instead of object[item] = loadedObject[item] I tried the following, but that actually failed:

const u = 'update:' + object + '.' + item
this.$emit(u, loadedObject[item] )

What would be the correct way to do this?

1
You’re not modifying a prop directly, Instead, you're modifying a nested value in an object, Vue doesn't detect that thus you do not see the warning message. A properly way is you can make a copy of object (globalStates), modify it and emit event to parent. But why don't you put loadLocalData method in parent component?ittus
this.$emit('update:propName', newProp) is the correct way to emit event for .sync. 'update:' + object + '.' + item is wrong, You are concat string with object. And I think .sync don't support nested object update.Morty Choi
Thanks Ittus, for explaining why the warning isn’t shown. I guess the correct answer is in your question: why not put int the parent (app.vue was getting messy, so I wanted to move as much functionality to components).kslstn
Thank you Morty, according to the closed feature request in my answer that is correct.kslstn

1 Answers

0
votes

The correct way would be to not sync objects, because sync does not support that: https://github.com/vuejs/vue/issues/6241

Alternative solutions are:

  1. Put the method in the parent

  2. Sync each property as a separate prop

  3. Use a data store: https://vuejs.org/v2/guide/state-management.html