Object.assign正在修改原始数组对象

时间:2018-05-24 10:19:20

标签: javascript arrays reactjs

我正在尝试在我的状态中修改特定索引的属性值此属性是post_comments但我的问题是状态正在被修改,即使我只是修改它的副本..代码工作我想要它是如何,但我正在修改状态,所以它可能很糟糕我如何解决这个问题?

socket.on('statusComment', (data) => {
    const mutator =  Object.assign([], this.state.getStatus);
    const index =  mutator.findIndex(i => i._id === data._id);
    mutator[index].post_comments = data.post_comments; // Replace old post_comments with data.post_comments 
    console.log(mutator) // Got the post_comments 
    console.log(this.state.getStatus) // Also modified 

    // Commented out setState
    // this.setState({
    //     getStatus: mutator
    // })
});

以下是socket

检测到的示例data
const data = {
  post_id: "5b0689f03fb2fd1404f1854d",
  post_comments: [{text: 'what'}]
}

这就是我的状态

   const data_arr = [
      {
        "post_img": [],
        "post_date": "2018-05-24T09:46:24.948Z",
        "post_comments": [
          {
            "comment_posted": "2018-05-24T09:46:31.015Z",
            "_id": "5b0689f73fb2fd1404f1854e",
            "comment_from": {
              "photo_url": "png",
              "_id": "5af16d60f3957c11e46500ae",
              "display_name": "Lumpo"
            },
            "comment_text": "kaka2"
          },
          {
            "comment_posted": "2018-05-24T09:47:42.752Z",
            "_id": "5b068a3e2fdd6f141d5ba995",
            "comment_from": {
              "photo_url": "png",
              "_id": "5af16d60f3957c11e46500ae",
              "display_name": "Lumpo"
            },
            "comment_text": "kaka!"
          }
        ],
        "_id": "5b0689f03fb2fd1404f1854d",
        "post_description": "get out\r\n",
        "post_by": {
          "photo_url": "png",
          "_id": "5af16d60f3957c11e46500ae",
          "display_name": "Lumpo"
        },
        "__v": 2
      }
    ]

Spread运算符无法使用Object.assign方法记录相同的内容 // console.log(mutator)

[
  {
    "post_img": [],
    "_id": "5b0694cc7925c914e4d95dda",
    "post_description": "test",
    "post_by": {
      "_id": "5af16d60f3957c11e46500ae",
      "display_name": "Lumpo",
      "photo_url": "png"
    },
    "post_comments": [
      {
        "_id": "5b0694d67925c914e4d95ddb",
        "comment_from": {
          "photo_url": "png",
          "_id": "5af16d60f3957c11e46500ae",
          "display_name": "Lumpo"
        },
        "comment_text": "This comment should only be in the mutator ",
        "comment_posted": "2018-05-24T10:32:54.937Z"
      }
    ],
    "post_date": "2018-05-24T10:32:44.613Z",
    "__v": 0
  }
]

// console.log(this.state.getStatus);

[
  {
    "post_img": [],
    "_id": "5b0694cc7925c914e4d95dda",
    "post_description": "test",
    "post_by": {
      "_id": "5af16d60f3957c11e46500ae",
      "display_name": "Lumpo",
      "photo_url": "png"
    },
    "post_comments": [
      {
        "_id": "5b0694d67925c914e4d95ddb",
        "comment_from": {
          "photo_url": "png",
          "_id": "5af16d60f3957c11e46500ae",
          "display_name": "Lumpo"
        },
        "comment_text": "This comment should only be in the mutator ",
        "comment_posted": "2018-05-24T10:32:54.937Z"
      }
    ],
    "post_date": "2018-05-24T10:32:44.613Z",
    "__v": 0
  }
]

5 个答案:

答案 0 :(得分:1)

Object.assign([], this.state.getStatus)

[]是一个数组,不是对象。这可能会导致问题。

编辑:看Josh的评论,它是一个对象,但也是一个数组。但是如果它是一个对象对象,行为将会有所不同。

答案 1 :(得分:1)

const mutator =  Object.assign([], this.state.getStatus);

它正在做shallow/reference数组副本。

因此,原始数组将被复制,因为它是使用引用。

使用spread operator创建数组的新副本,然后执行JSON.stringify,然后执行JSON.parse.U需要深层副本。

let mutator = [...this.state.getStatus];
mutator = JSON.parse(JSON.stringify(mutator));

答案 2 :(得分:1)

你可以像这样复制你的数组:

 const mutator =  [...this.state.getStatus];

答案 3 :(得分:0)

在不复制引用的情况下制作现有数组副本的最快方法如下:

const mutator = this.state.getStatus.slice(0);

如此处所述https://developer.mozilla.org/de/docs/Web/JavaScript/Reference/Global_Objects/Array/slice

答案 4 :(得分:0)

您的州是一个包含对象数组的对象。

首先复制状态并重置映射getStatus的数组getStatus。当找到需要更改的状态项时,您复制该项,但将post_comments设置为其他值(请参阅下面的代码)。

this.setState({
  ...this.state,//copy state
  getStatus: this.state.getStatus.map(//getStatus is a new array
    (item,index)=>
      (item._id===data._id)//if item._id is data._id
        ? {...item,post_comments:data.post_comments}//copy item but reset post_comments
        : item//not the item we are looking for, return item (not changed copy)
  )
})

如果您需要更多帮助,请告诉我。

使用JSON.parse(JSON.stringify(state)))将导致所有组件重新渲染,即使它们的状态部分没有变化(深拷贝与浅拷贝)。您可以使用shouldComponentUpdate查看状态是否实际发生了变化,并告诉您不要重新渲染未发生这种情况的组件。然而;因为你是深刻复制所有东西(不仅是改变的项目),你不能这样做。

这是一个基本组件的示例,它检查传递给它的状态是否实际更改了引用并应重新呈现:

import React from 'react';
class OnlyIfChanged extends React.Component {
  shouldComponentUpdate(nextProps, nextState) {
    return nextProps.state !== this.props.state;
  }
}
export default OnlyIfChanged;