5
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Reactのstateはどのように推移するのか

Posted at

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になっているので見ていく。

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を見に行く。

ReactUpdates.js
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がどのように処理されているかを調べてみる。
狙いはこの関数が呼ばれているところ。

ReactUpdates.js
function runBatchedUpdates(transaction) {
  ...,
}

まずはここで呼ばれている。

ReactUpdates.js
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まで遡る必要がありそう。

つづく・・・

5
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?