我正在尝试在我的状态中修改特定索引的属性值此属性是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
}
]
答案 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;