20

In vue.js what is the right way to edit prop without changing parent data? What I mean by that is whenever we pass any property from parent to child in vue.js then if we make any change to that property in child component then the change is also reflected in parent's component.

Is there any way in vue.js to make a local copy of passed property in a child?

I googled this but everywhere it is written that we can achieve this by doing this.

 props:["user"],
  data(){
    return {
      localUser: Object.assign({}, this.user)
    }
  }

here the user is passed an object and I am creating a copy of it in local user but it doesn't work at all, the local user is undefined.

Have you encountered a scenario like this where you have to make changes to a parent property in child component without affecting the state of parent component i.e- making your own copy in child and then edit it?

Any insights on this will be helpful.

I have also read somewhere that in In vue@2.3.3,when we want to pass a prop from Father to Child component, we need to manually create a local data to save the prop, that makes lots of useless works.

we can maually create the local data like this :

props: ['initialCounter'],
data: function () {
    return { counter: this.initialCounter }
}

but this is not working in my case as well. I am using vue cli 3.0.1 for the developemnt purpose.

Here is my code for the same.

In my application I have a list view.

enter image description here

When user clicks on the See Focused View button user is redirected to below mentioned view i.e is actaully a bootstrap - modal view.

enter image description here

Here user can edit the value of Name, but as I am passing name here as a property from aprent component so editing it here causes it to update on parent component as well i.e in the list view as well.

Divyanshu Rawat
  • 4,421
  • 2
  • 37
  • 53

1 Answers1

30

In your fiddle, the child component is using Object.assign() to create a copy of data, which is an array of objects. However, this only creates a shallow copy, so the array elements would still refer to the original instances, leading to the behavior you're seeing.

A few solutions to deep copy the array:

  • Use JSON.parse(JSON.stringify(this.data)), which works reasonably well for primitive object properties (String, Number, BigInt, Boolean, undefined, and null):

    data() {
      return {
        local_data: JSON.parse(JSON.stringify(this.data))
      }
    }
    

    (demo 1)

  • Map the objects into new ones, which works well if the depth is only 1 (nested arrays/objects will still be shallow copied):

    data() {
      return {
        local_data: this.data.map(x => ({...x}))
      }
    }
    

    (demo 2)

  • Use a utility library, such as lodash's cloneDeep:

    data() {
      return {
        local_data: _.cloneDeep(this.data)
      }
    }
    

    (demo 3)

tony19
  • 125,647
  • 18
  • 229
  • 307
  • 3
    This was a great explanation that I needed after a few hours of getting no where. – Chase Ernst Sep 17 '20 at 19:53
  • This helps so much, I love the multiple examples. Does demo 1 have any issues with date objects in the arrays? – Caine Nielsen Nov 09 '20 at 23:59
  • 1
    @CaineNielsen `JSON.stringify` will convert `Date` objects to `String` (via `Date#toString`), so they would need to be [revived in `JSON.parse`](https://stackoverflow.com/questions/14488745/javascript-json-date-deserialization). – tony19 Nov 10 '20 at 00:31
  • It still feels hacky to do this cloning stuff. Is there really no better solution than cloning objects? – Walnussbär Jul 27 '23 at 15:29
  • @Walnussbär Objects are passed by reference in JavaScript, so cloning is the only way to separate the original reference from the new object (as of 2023...maybe the language could change in the future). – tony19 Jul 27 '23 at 19:12
  • I know, but every time I have to do this it feels not good/ like a big overhead. But yeah, the language needs to change in order to circumvent this. – Walnussbär Jul 28 '23 at 21:29