1

I'm currently working in a page with parent/child components. Somehow my child component gets updated when I manage its variables in the parent component. What I'm trying to do:

  1. My child component has a 'site' variable with all the data i need to send via API
  2. My parent component has a Save button to send the child data to the Back-end
  3. When 'site' changes in the child component, I'm emitting an event @change to the parent component
  4. The @change event contains all the data I need, but not in the format I want
  5. There is a function submit() that gets this data and modify the one of the arrays so that this: ['foo','bar'] becomes this 'foo,bar'
  6. The problem when I do the step '5' my child component gets updated

The child component inside the parent component

<configuracoes :configuracoes="configuracoes" @change="setData"
      v-if="currentPage === 'configs'"/>

The change event emitted by the child component

this.$emit("change", this.site);

The important part of 'site' var

site: {
  seo: {
   keywords: [],
             ...
           },
          ...
    },

The setData() function

setData(data) {
    this.data = data;
},

The submitData() function

submitData() {
    if (this.currentPage === "configs") {

        let data = ({}, Object.assign(this.data))
        let keywords = data.seo.keywords.join(',')
        data.seo.keywords = keywords
        this.$store.dispatch("sites/updateSite", {
            empresa_id: this.user.empresa_id,
            site_id: this.siteId,
            dados: data,
        });
    }
}

As you can see, I'm declaring another variable let data to avoid updating this.site variable, but no success

Marian
  • 3,789
  • 2
  • 26
  • 36

1 Answers1

0

First of all, there is an issue with how you're "copying" your this.data object.

let data = ({}, Object.assign(this.data)); // this doesn't work
console.log(data === this.data); // true

const dataCopy = Object.assign({}, this.data); // this works
console.log(dataCopy === this.data); // false

The way Object.assign works, all the properties will be copied over into the first argument. Since you only pass a single argument, it doesn't change and is still pointing to the same old object.


If you use the correct way, you will most likely still run into the same issue. The reason is that data.seo is not a primitive value (a number or a string), but is an object.

This means that the whole seo object will be copied over into the new copy. In other words, even though dataCopy !== this.data, dataCopy.seo === this.data.seo. This is known as "shallow copy".

You want to make sure you DO NOT modify the original seo object, here are a few ways to do that.

let goodCopy;
const newKeywords = this.data.seo.keywords.join(',');

// use object spread syntax
goodCopy = {
    ...this.data,
    seo: {
        ...this.data.seo,
        keywords: newKeywords,
    },
};

// use Object.assign
goodCopy = Object.assign(
    {},
    this.data,
    {
        seo: Object.assign(
            {},
            this.data.seo,
            {keywords: newKeywords}),
    });

// create a copy of "seo", and then change it to your liking
const seoCopy = {...this.data.seo};
seoCopy.keywords = newKeywords;
goodCopy = Object.assign({}, this.data, {seo: seoCopy});

this.$store.dispatch('sites/updateSite', {
    empresa_id: this.user.empresa_id,
    site_id: this.siteId,
    dados: goodCopy,
});

If you want to read up on ways to copy a JavaScript object, here's a good question.

Marian
  • 3,789
  • 2
  • 26
  • 36
  • Thank you for your answer. Yesterday i was looking for a fix and found how Objects and references work. Despite beeing a programmer for so long, there is still a lot to learn (i cant vote because i dont have enough reputation) – Arthur wegner wippel Jul 08 '20 at 11:23