代码之家  ›  专栏  ›  技术社区  ›  sofs1 Romain Manni-Bucau

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

  •  1
  • sofs1 Romain Manni-Bucau  · 技术社区  · 6 年前

    Documentation

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

    //错误

    this.state.comment = 'Hello';
    

    而是使用setState():

    //更正

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

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

    1 回复  |  直到 6 年前
        1
  •  1
  •   Andrew    6 年前

    当你使用像react这样的高级框架时,他们不会费心解释为什么,因为对于一篇简单的文章来说,它太复杂了。理解为什么需要深入理解react,以及普通javascript在幕后是如何工作的。查看源代码是您的一个选择,但当您以面值获取他们的文档时,生活会更轻松。

    虚拟dom:

    react保留页面的前一个状态的副本。当它决定应该重新绘制什么和不应该重新绘制什么时,它将它用作一个参考点。当您单击一个按钮时,整个页面不需要将整个dom重新绘制为完全相同的值,但是javascript有点糟糕的是

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

    在虚拟dom和下一个react想要重新绘制的dom之间寻找差异是不可能的,因为javascript没有能力识别

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

    我的例子并不能解释手动改变状态的弱点。就是这个。

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

    一系列 [10] 新值注册为等于 [] 因为相等是通过引用完成的,并且向现有元素添加一个值仍然等于它先前的状态。这里是如何解决它。你这么做不是巧合

        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触发一个rerender

    重新提交程序不是对dom的完全重新绘制。当它发现差异时,它将触发对传入的特定元素的重新绘制。