forceUpdate()与带有回调的this.setState()

时间:2016-02-09 04:48:31

标签: reactjs

这样做的原因是处理具有自己功能的state变量。我有两种方式可以想到。一种方法是通过调用状态函数直接改变this.state(好吧,我知道它是不鼓励的),然后调用forceUpdate()并处理它带来的内容。另一种是做回调函数。哪种方法适当?

以下是我所谈论的一个例子。我正在使用Vis.js,他们的DataSet对象允许您将数据添加到现有数据集 - 例如节点和边缘。

  addDataToGraph: function(data) {
    // Is this the proper way to do something like this?
    this.state.graphData.nodes.add(nodes);
    this.state.graphData.edges.add(edges);
    this.forceUpdate();

    // Or is this the right way - the question I am posing here
    this.setState({
      currentChunk: data.currentChunk,
      totalChunks: data.totalChunks
    }, function() {
      this.state.graphData.nodes.add(data.nodes);
      this.state.graphData.edges.add(data.edges);
    }.bind(this));
  }

2 个答案:

答案 0 :(得分:6)

你绝对不应该改变this.state或其中的任何内容。来自React Component API docs

  

不要直接改变this.state,因为之后调用setState()可能会替换你所做的突变。把this.state看作是不可变的。

     

setState()不会立即改变this.state,但会创建挂起状态转换。在调用此方法后访问this.state可能会返回现有值。

     

无法保证对setState的调用进行同步操作,并且可以对调用进行批处理以获得性能提升。

     

除非在shouldComponentUpdate()中实现条件呈现逻辑,否则setState()将始终触发重新呈现。如果正在使用可变对象且无法在shouldComponentUpdate()中实现逻辑,则仅当新状态与先前状态不同时调用setState()将避免不必要的重新渲染。

即使你的第二个例子在这里也不正确,因为你仍在改变this.state。第二个参数仅仅是状态更新时的回调。您想要做的是以某种方式获取新对象并将其提供给setState。对Vis.js不太熟悉,这似乎有点棘手,因为它似乎没有任何返回全新/不可变数据集的操作。甚至没有复制或克隆操作。您似乎每次都必须实际创建一个全新的vis.DataSet并添加原始数据,然后添加新数据,然后this.setState( { graphData: newGraphData, ... } )

最终,这可能是纯粹的'并且正确的方法来做到这一点。

所有这一切,以及一个大的YMMV警告 - 因为没有明显的方法将vis.DataSet视为不可变的,你可以选择第一个选项。

在文档中采取警告的第一部分:

  

之后调用setState()可能会替换你所做的突变

在这种情况下会发生什么?没有什么,因为你所在州的实际对象是可变的,它只是永远的一个参考。如果React'取代它'它只是用它自己取而代之。换句话说,只要您从未使用全新的DataSet调用setState,就不会在意外时间将其替换为意外的内容。

这里的一个大问题是,调用forceUpdate会强制重新渲染,这可能会很慢。但是,无论如何,当你调用该函数时,无论怎么回事,你都希望它能够重新渲染,所以...... 实用地说你可能还可以:)

答案 1 :(得分:2)

要改变组件的状态,我们应该总是使用 this.setState() ,因为它告诉React组件状态发生了变化,然后React会小心以高效的方式重新渲染。但是,我们也可以使用 this.state.yourProperty = somethingNew 来改变状态对象,但是我们永远不应该这样做因为它太过显示而且React不知道我们的状态因此我们必须通过调用 this.forceUpdate() 来明确触发重新渲染。使用 this.forceUpdate 的一个很好的例子是与其他库如D3.js的集成。 D3有自己的数据集,因此假设如果D3数据集中的某些内容发生变化,则需要告诉React'嘿! React我改变了我的一些东西,现在我需要重新渲染'所以D3将通过使用 this.forceUpate() 回调出反应。< / p>