合并
然后我们来看一道题目:
function incrementMultiple() {
this.setState({count: this.state.count + 1});
this.setState({count: this.state.count + 1});
this.setState({count: this.state.count + 1});
}
请问这个时候,this.state.count的值为多少呢?答案为1
浅析
数据的合并
Object.assign({}, prevState, partialState)
// 也就是说
this.setState({Age: '22'})
this.setState({Name: 'srtian'})
// 等价于
this.setState({Age: '22', Name: 'srtian})
this.state = {
message: "Hello World",
name: "wyx"
}
this.setState({
message: "你好啊,帅哥"
});
通过setState去修改message,是不会对name产生影响的;
源码中其实是有对 原对象 和 新对象进行合并的:
setState本身的合并
this.setState会通过引发一次组件的更新过程来引发重新绘制。也就是说setState的调用会引起React的更新生命周期的四个函数的依次调用:
shouldComponentUpdate
componentWillUpdate
rende
componentDidUpdate
我们都知道,在React生命周期函数里,以render函数为界,无论是挂载过程和更新过程,在render之前的几个生命周期函数,this.state和Props都是不会发生更新的,直到render函数执行完毕后,this.state才会得到更新。(有一个例外:当shouldComponentUpdate函数返回false,这时候更新过程就被中断了,render函数也不会被调用了,这时候React不会放弃掉对this.state的更新的,所以虽然不调用render,依然会更新this.state。)
React的官方文档有提到过这么一句话:
状态更新会合并(也就是说多次setstate函数调用产生的效果会合并)。
看源码
ReactComponent.prototype.setState = function(partialState, callback) {
invariant(
typeof partialState === 'object' ||
typeof partialState === 'function' ||
partialState == null,
'setState(...): takes an object of state variables to update or a ' +
'function which returns an object of state variables.',
);
this.updater.enqueueSetState(this, partialState);
if (callback) {
this.updater.enqueueCallback(this, callback, 'setState');
}
};
enqueueSetState: function(publicInstance, partialState) {
if (__DEV__) {
ReactInstrumentation.debugTool.onSetState();
warning(
partialState != null,
'setState(...): You passed an undefined or null state object; ' +
'instead, use forceUpdate().',
);
}
var internalInstance = getInternalInstanceReadyForUpdate(
publicInstance,
'setState',
);
if (!internalInstance) {
return;
}
var queue =
internalInstance._pendingStateQueue ||
(internalInstance._pendingStateQueue = []);
queue.push(partialState);
enqueueUpdate(internalInstance);
}
// 通过enqueueUpdate执行state更新
function enqueueUpdate(component) {
ensureInjected();
// batchingStrategy是批量更新策略,isBatchingUpdates表示是否处于批量更新过程
// 最开始默认值为false
if (!batchingStrategy.isBatchingUpdates) {
batchingStrategy.batchedUpdates(enqueueUpdate, component);
return;
}
dirtyComponents.push(component);
if (component._updateBatchNumber == null) {
component._updateBatchNumber = updateBatchNumber + 1;
}
}
// 对_pendingElement, _pendingStateQueue, _pendingForceUpdate进行判断,
// _pendingStateQueue由于会对state进行修改,所以不为空,
// 然后会调用updateComponent方法
performUpdateIfNecessary: function(transaction) {
if (this._pendingElement != null) {
ReactReconciler.receiveComponent(
this,
this._pendingElement,
transaction,
this._context,
);
} else if (this._pendingStateQueue !== null || this._pendingForceUpdate) {
this.updateComponent(
transaction,
this._currentElement,
this._currentElement,
this._context,
this._context,
);
} else {
this._updateBatchNumber = null;
}
},
其中这段代码需要额外注意:
// batchingStrategy是批量更新策略,isBatchingUpdates表示是否处于批量更新过程
// 最开始默认值为false
if (!batchingStrategy.isBatchingUpdates) {
batchingStrategy.batchedUpdates(enqueueUpdate, component);
return;
}
dirtyComponents.push(component);
if (component._updateBatchNumber == null) {
component._updateBatchNumber = updateBatchNumber + 1;
}
上面这段代码的意思就是如果是处于批量更新模式,也就是isBatchingUpdates为true时,不进行state的更新操作,而是将需要更新的component添加到dirtyComponents数组中。
如果不处于批量更新模式,则对所有队列中的更新执行batchedUpdates方法。
然后可以找到了这个batchedUpdates:
var ReactDefaultBatchingStrategy = {
// 也就是上面提到的默认为false
isBatchingUpdates: false,
// 这个方法只有在isBatchingUpdates: false时才会调用
// 但一般来说,处于react大事务中时,会在render中的_renderNewRootComponent中将其设置为true。
batchedUpdates: function(callback, a, b, c, d, e) {
var alreadyBatchingUpdates = ReactDefaultBatchingStrategy.isBatchingUpdates;
ReactDefaultBatchingStrategy.isBatchingUpdates = true;
// The code is written this way to avoid extra allocations
if (alreadyBatchingUpdates) {
return callback(a, b, c, d, e);
} else {
return transaction.perform(callback, null, a, b, c, d, e);
}
},
即:
当我们调用setState时,最终会通过enqueueUpdate执行state更新,就像上面那样有两种更新的模式,一种是批量更新模式,将组建保存在dirtyComponents;另一种非批量模式,将会遍历dirtyComponents,对每一个dirtyComponents调用updateComponent方法。
本文系转载,前往查看
如有侵权,请联系 cloudcommunity@tencent.com 删除。
本文系转载,前往查看
如有侵权,请联系 cloudcommunity@tencent.com 删除。