为什么我们不应该直接在ReactJS中修改状态?

时间:2018-07-04 22:09:27

标签: javascript reactjs

Documentation

例如,这不会重新渲染组件:

//错误

this.state.comment = 'Hello';

相反,请使用setState():

//正确

this.setState({comment: 'Hello'});

但是,为什么没有答案?使用第二个是正确的理由是什么?

1 个答案:

答案 0 :(得分:1)

当您使用像React这样的高级框架时,他们不会费心解释如此详细的原因,因为对于简单的文章而言,它太复杂了。理解为什么需要深入了解React以及原始JavaScript的工作原理。查看源代码是您的一种选择,但是当您以其实际价值看文档时,工作会更轻松。

虚拟DOM:

React保留页面先前状态的副本。当它决定应该重新粉刷什么和不应该粉刷什么时,它将其用作参考点。当您单击一个按钮时,整个页面不需要将整个DOM重新绘制为完全相同的值,但是JavaScript有点可笑的事实是

JavaScript中的对象不存在按值的相等性

因为JavaScript无法识别

,所以不可能在虚拟DOM和React想要重绘的下一个DOM之间找到差异。

console.log([] === [])

我的示例并未说明手动更改状态的弱点。是这个。

this.state = {}
this.state.arr = []
const prevArr = this.state.arr
this.state.arr.push(10)

console.log(this.state.arr === prevArr)

具有新值的[10]数组被注册为等于[],因为相等是通过引用完成的,并且向现有元素添加值仍等于其先前状态。这是解决方法。您也可以在React中执行此操作并非偶然

    this.state = {}
    this.state.arr = []
    const prevArr = [...this.state.arr]
    prevArr.push(10)
    this.state.arr

    console.log(this.state.arr === prevArr)

制作数组的新副本会保留指向值的所有指针,但这是您硬件内存中的独特实体。现在他们不同了。当React遍历其虚拟DOM时,它现在可以注册将10插入到数组中,并希望将其反映在DOM的下一次迭代中。

this.setState触发重新渲染

重新渲染不是对DOM的完全重新绘制。发现差异时,它会触发您要传递的特定元素的重新绘制。