在ReactJS中正确修改状态对象数组

时间:2018-01-12 19:31:10

标签: arrays reactjs

我有一个位于this.state.points的点数组。我有一个updatePoint()函数,用于更新此数组中的各个点。我认为使用.slice()会让我的状态保持不变,直到我调用setState,但是当我设置了points [i]的值后,我调试了this.state.points,我看到它已经更新了。在调用setState之前,如何防止状态更新?

updatePoint(i, point) {
    console.log('updatePoint '+i)
    let points = this.state.points.slice()
    points[i] = point
    this.setState({points: points})
  }

此版本也不起作用:

updatePoint(i, point) {
    console.log('updatePoint '+i)
    let points = this.state.points.slice()
    points.forEach((j) => {
      points[j] = Object.assign({}, this.state.points[j])
    })
    points[i] = point
    this.setState({points: points})
  }

2 个答案:

答案 0 :(得分:0)

Array.slice不执行深层复制,因此如果您的this.state.points是一个对象数组,则还需要复制这些对象项。

您可以使用Object.assign复制对象。

答案 1 :(得分:0)

您可以使用ES6附带的扩展运算符(...):

updatePoint(i, point) {
   console.log('updatePoint '+i)
   let points = [...this.state.points]
   console.log("points", points);
   points[i] = point;
   console.log("state",this.state.points);
   this.setState({points: points})
   console.log(this.state.points);
}

您可以在此处进行测试(并尝试检查您自己环境中的console.log):

class Hello extends React.Component {
  constructor(props){
  	super(props);
    this.updatePoint = this.updatePoint.bind(this);
    this.state = {
    	points: [{name: "uno"},
      				{name: "dos"},
               {name: "tres"}]
      };
    console.log(this.state.points);
      
  }
  // i = 1, name: ocho
  updatePoint = (i, point) => {
    console.log('updatePoint '+ i)
    console.log("spread", [...this.state.points]);
    const newPoints = [...this.state.points];
    console.log("points", newPoints);
    newPoints[i] = point;
    console.log("state",this.state.points);
    this.setState({
    		points: newPoints
    });

  }
  
  render() {
  	const nowState = this.state.points.map(item => <p key={item.name}>{item.name}</p>);
    return (
    <div>Hello 
    <button 
      onClick={() => this.updatePoint(1, {name: "ocho"})}
    >Click
    </button>
    <p>Current state
    {nowState}</p>
    </div>);
  }
}

ReactDOM.render(
  <Hello name="World" />,
  document.getElementById('container')
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="container">
  <!-- This element's contents will be replaced with your component. -->
</div>

有关点差运算符的更多信息: 来自https://docs.microsoft.com/en-us/scripting/javascript/reference/spread-operator-decrement-dot-dot-dot-javascript

  

允许从可迭代表达式(例如另一个数组文字)初始化数组文字的某些部分,或允许将表达式扩展为多个参数(在函数调用中)。

https://redux.js.org/docs/recipes/UsingObjectSpreadOperator.html

  

另一种方法是使用为下一版JavaScript提出的对象扩展语法,它允许您使用spread(...)运算符以更简洁的方式将可枚举属性从一个对象复制到另一个对象。