I'm passing a data object from component to component through props in Nuxt 3:
<template>
<div>
<Tests :objParent="objParent" />
</div>
</template>
<script setup>
const objParent = {title: {en:"title en", fr:"title fr"}}
</script>
<template>
<div >
<h1>objParent : {{ props.objParent.title.en }}</h1>
<v-text-field label="label" v-model="objChild.title.en" />
<h1>objChild : {{ objChild.title.en }}</h1>
</div>
</template>
<script setup>
const props = defineProps(["objParent"]);
const objChild = ref({...props.objParent});
</script>
The problem is, if I mutate the nested objects from objChild
, they will still be mutated in the original nested objects from the parent component.
I don't have the same problem passing an object without nested objects - e.g.:
// title can be mutated without mutating the original object
const objParent = {title: "title en"}
I did some research and I found this solution:
const objChild = ref(JSON.parse(JSON.stringify(props.objParent)));
Is it a valid solution?
To expand on the comment by Emil, since your new object is created using the props from the original object directly (via spread operator), every nested object will keep pointing to the ones nested in the original parent object.
This happens because in JavaScript objects differ from primitive values as they are a reference type. When you assign an object to a variable, you assign a reference to the object - meaning if you keep assigning the same object in other places, it will still be pointing to the original object, and the same goes for all of its nested objects.
So:
const x = { hello: 'world' };
const y = { x };
const z = { y };
z.y.x.hello = 'kitty';
// {hello: 'kitty'}
console.log(x);
As you pointed out yourself, one easy technique to produce deep copies in JavaScript would be serializing/deserializing it to and from a JSON string:
const x = { hello: 'world' };
const y = { x };
const z = JSON.parse(JSON.stringify({ y }));
z.y.x.hello = 'kitty';
// {hello: 'world'}
console.log(x);
// {y: {x: {hello: 'kitty'}}}
console.log(z);
To answer your question - yes, it is a valid, working and widely used means of creating deep clones. Mind you, however, that not everything can be serialized to JSON, including Symbol-keyed properties, BigInt
values and circular references. See caveats here.
If the data you expect to receive already comes from a REST API, it will most likely not contain any unserializable data.
You can find other alternatives (and their caveats) in this Stack Overflow question.