admin管理员组

文章数量:1353256

I wonder if I did something wrong because as far as I know: Object.assign and spread operator will create new object, therefore we can avoid mutate the internal state with is a bad practice. But in my project those two don't seem to work.

First, in my constructor, I setup the state as below:

this.state = {
  article: {
    title: "",
    alias: "",
    category: "JAVA",
    steps: [
      {
        stepId: 1,
        title: "Dummy title",
        description: "The quick brown fox jump over the lazy dog",
        length: 30
      }
    ]
  },
  description: "",
  newStep: {
    title: "",
    length: 0
  }
}

Later, I add an addStep() function:

addStep() {

  console.log(this.state.article.steps);

  let article = { ...this.state.article };

  article.steps.push({
    stepId: _.last(this.state.article.steps).stepId + 1,
    title: this.state.newStep.title,
    length: this.state.newStep.length,
    description: "",
  });

  console.log(this.state.article.steps);
}

And here the result:

As you can see this.state.article.steps has been mutated. The same goes for Object.assign. Finally I decide to use and that solved my problem.

let article = JSON.parse(JSON.stringify(this.state.article));

Result:

I wonder if I did something wrong because as far as I know: Object.assign and spread operator will create new object, therefore we can avoid mutate the internal state with is a bad practice. But in my project those two don't seem to work.

First, in my constructor, I setup the state as below:

this.state = {
  article: {
    title: "",
    alias: "",
    category: "JAVA",
    steps: [
      {
        stepId: 1,
        title: "Dummy title",
        description: "The quick brown fox jump over the lazy dog",
        length: 30
      }
    ]
  },
  description: "",
  newStep: {
    title: "",
    length: 0
  }
}

Later, I add an addStep() function:

addStep() {

  console.log(this.state.article.steps);

  let article = { ...this.state.article };

  article.steps.push({
    stepId: _.last(this.state.article.steps).stepId + 1,
    title: this.state.newStep.title,
    length: this.state.newStep.length,
    description: "",
  });

  console.log(this.state.article.steps);
}

And here the result:

As you can see this.state.article.steps has been mutated. The same goes for Object.assign. Finally I decide to use and that solved my problem.

let article = JSON.parse(JSON.stringify(this.state.article));

Result:

Share Improve this question edited May 29, 2020 at 22:31 David Buck 3,84538 gold badges50 silver badges69 bronze badges asked Jan 17, 2018 at 5:18 Lê Quang BảoLê Quang Bảo 2,8702 gold badges32 silver badges40 bronze badges
Add a ment  | 

3 Answers 3

Reset to default 5

Object.assign{} and object spread won't deep clone an object.

It will mutate steps.

It is discussed in the following thread:

How do I correctly clone a JavaScript object?

let article = { ...this.state.article }; is only making a shallow copy of the object. You can manually make new child keys with something like:

let article = {
  ...this.state.article,
  steps: [...this.state.article.steps]
};

There are many ways to deal with the problem of trying to clone a deeply nested object. This is just one of them.

You could spread the original state this.state.article and overwrite the nested values (like steps) with another spread.

let article = {
  ...this.state.article,
  steps: [...this.state.article.steps]
};

本文标签: javascriptObject assign and spread operator mutate React stateStack Overflow