How can I clone data from Vuex state to local data?
Asked Answered
A

4

13

How can I clone data from vuex state to local data attribute?

State

this.tsStore.shemes

Data Attribute

data () {
  return { shemes: [] }
}

I've tried do this in updated () this.shemes = this.tsStore.shemes but it's seems like it has a binding left.. because when i delete one item in this.shemes on click i've also delete that item in the state and get the error of "Do not mutate vuex store state outside mutation handlers".

I need to clone the state and do what ever I need to do with that data and on the same time don't affect my state state.

Arlynearlynne answered 30/9, 2018 at 19:39 Comment(0)
B
25

Try

this.shemes = JSON.parse ( JSON.stringify ( this.tsStore.shemes) )

This will clone all value and objects from the array in the store.

Balladmonger answered 30/9, 2018 at 19:47 Comment(8)
Thanks, it works! Where should I put this, computed or created?Arlynearlynne
It seems that this.shemes is empty when I refresh the browserArlynearlynne
data() variables can be accessed only after the component mounts. Try calling this in mounted()Balladmonger
console.log( JSON.stringify ( this.tsStore.shemes) ) and check the stringifying procedure. It should show you the scheme in the consoleBalladmonger
It's empty on refreshing, but I can see the data from the Vue ConsoleArlynearlynne
If I console.log it in updated() it appear again, I get the data but I'cant do the parse in there, right?Arlynearlynne
No, I don't think there is an issue from parsing in updated.Balladmonger
This does not work if you have dates/sets/maps/etc... in your object, in that case see the (underrated) answer from @kissu below...Archway
U
6

You need to create a new array. this.tsStore.shemes give you a reference to the bound array. You can try to use the spread operator or arr.slice() to create a new array with the same content. notice that this is a shallow copy.

this.shemes = [...this.tsStore.shemes]

or

this.shemes = this.tsStore.shemes.slice()
Unsteady answered 30/9, 2018 at 19:44 Comment(2)
The spread operator works like a charm. The shallow copy ensures that the original state data is untouched.Zenia
Side problem with this...it only works on the direct properties of the object you are cloning. It does not work if the object you are cloning has nested properties and those nested properties also have getters/setters on them from the state. It is a REALLY good option, just didn't work for my case of objects within an array, where the array was a property on the watched object.Diplomatic
I
4
data(){
  return {
    shemes: null,
  }
},
beforeMount() {
  this.shemes = this.stateShemes
},
computed: {
  stateShemes() { return this.tsState.shemes }
  // OR that's how I do
  stateShemes() { return this.$store.getters['shemes'] }
}

UPDATE

So you get some value from your state by using computed variables. You cannot just assign the value from you store in the data() block. So you should do it beforeMount. That way if you have a watcher for shemes variable, it won't trigger on assigning computed value. If you put it in mounted() hook, the watcher will trigger.

Also, can you explain why do you use this call this.tsState.shemes instead of this.$store.getters.shemes?

Ingrid answered 1/10, 2018 at 14:34 Comment(9)
Simply posting some code isn't terribly helpful. Can you explain your code? That way others can understand and learn from your answer instead of just copying & pasting some code from the web.Pastypat
Sorry for that. Updated my answer.Ingrid
tsState is an mapStateArlynearlynne
@Arlynearlynne did you try me answer? if you have any questions be free to ask me.Ingrid
I did and it seems to work but I've got this error when I'm trying to delete/remove an item from this.shemes based on click event Do not mutate vuex store state outside mutation handlers I'm trying to remove the first item in this.shemes with the function shift()Arlynearlynne
const mutations = { 'REMOVE_THING' (state, name) { state.shemes.shift() },Ingrid
this must be in your store. and to call mutation, create an actionIngrid
removeSheme ({ commit }, name) { commit('REMOVE_THING', name) },Ingrid
in your vue component: this.$store.dispatch('REMOVE_THING', name)Ingrid
T
4

Using cloneDeep is still the best way to go, here is an example

<script>
import { cloneDeep } from 'lodash-es'

...
const properlyClonedObject = cloneDeep(myDeeplyNestedObject)
...
</script>

It's bullet proof, battle-tested and is also a tree-shakable function.

If you need this for Nuxt, here is how to achieve this.

Trustless answered 17/12, 2021 at 14:32 Comment(2)
Is there a particular reason to use 'cloneDeep' instead of creating a deep copy using JSON.parse(JSON.stringify(...)) ?Anarchic
@Anarchic this is explained in my the best way to go link!Trustless

© 2022 - 2024 — McMap. All rights reserved.