这样做的原因是处理具有自己功能的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));
}
答案 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>