InitialState
React.createClass
内でgetInitialState
を定義していればそれが初期値。
定義しない場合はnull。
setState(partialState, callback)
this.updater.enqueueSetState(this, partialState);
if (callback) {
this.updater.enqueueCallback(this, callback);
}
this
はReact.createClassの引数のobjectであることに注意する。
ここではこのobjectをpublicInstance
と呼ぶことにする。
また初回に呼び出される場合は、this.state=initialState
である。
この時点でupdaterはReactUpdateQueue
になっているので見ていく。
var ReactUpdateQueue = {
...,
enqueueSetState: function(publicInstance, partialState) {
var internalInstance = getInternalInstanceReadyForUpdate(
publicInstance,
'setState'
);
if (!internalInstance) {
return;
}
var queue =
internalInstance._pendingStateQueue ||
(internalInstance._pendingStateQueue = []);
queue.push(partialState);
enqueueUpdate(internalInstance);
},
...,
};
一つずつ処理を追っていく。
function getInternalInstanceReadyForUpdate(publicInstance, callerName) {
var internalInstance = ReactInstanceMap.get(publicInstance);
...,
return internalInstance;
}
internalInstanceは_currentElement.type
にpublicInstanceを持つ。
queueは初回はnullなので[]で初期化。
queueに新しいstateを詰める。
そしてinternalInstanceに対してupdateをかける。
function enqueueUpdate(internalInstance) {
ReactUpdates.enqueueUpdate(internalInstance);
}
ReactUpdatesを見に行く。
function enqueueUpdate(component) {
ensureInjected();
// Various parts of our code (such as ReactCompositeComponent's
// _renderValidatedComponent) assume that calls to render aren't nested;
// verify that that's the case. (This is called by each top-level update
// function, like setProps, setState, forceUpdate, etc.; creation and
// destruction of top-level components is guarded in ReactMount.)
if (!batchingStrategy.isBatchingUpdates) {
batchingStrategy.batchedUpdates(enqueueUpdate, component);
return;
}
dirtyComponents.push(component);
}
!batchingStrategy.isBatchingUpdatesはmountが完了していればtrueなのでdirtyComponents=[]にinternalInstanceを詰める。
さて、詰めたのはいいが、いつ実行されるんだ・・?
Queueがどのように処理されているかを調べてみる。
狙いはこの関数が呼ばれているところ。
function runBatchedUpdates(transaction) {
...,
}
まずはここで呼ばれている。
var flushBatchedUpdates = function() {
while (dirtyComponents.length || asapEnqueued) {
if (dirtyComponents.length) {
var transaction = ReactUpdatesFlushTransaction.getPooled();
// perform=runBatchedUpdates(transactoin)
transaction.perform(runBatchedUpdates, null, transaction);
ReactUpdatesFlushTransaction.release(transaction);
}
...,
}
};
var ReactUpdates = {
...,
flushBatchedUpdates: flushBatchedUpdates,
...,
};
しかしながらReactUpdates.flushBatchedUpdates
が呼ばれている気配がmount時にはないので、injectまで遡る必要がありそう。
つづく・・・