Understanding The React Source Code - UI Updating (Transactions) VII

Last time we discussed the core Transaction class and ReactDefaultBatchingStrategyTransaction. The instantiation is not the sole Transaction involved in UI updating but merely the one that leads.

In this post, we are going to examine the other Transactions which, together with ReactDefaultBatchingStrategyTransaction, outline the UI updating processing logic.

renderers/shared/stack/reconciler/ReactUpdates.js: defines flushBatchedUpdates() that is the entry point method of this post; it also defines ReactUpdatesFlushTransaction, one of the Transaction s we are going to discuss

shared/utils/PooledClass.js: defines PooledClass for enabling instance pooling

renderers/dom/client/ReactReconcileTransaction.js: defines ReactReconcileTransaction, another Transaction we are going to discuss

We start with the ReactUpdates.flushBatchedUpdates() {last post *8}.

As mentioned before, it processes all the dirtyComponents by initiating a ReactUpdatesFlushTransaction that will invoke runBatchedUpdates eventually.

PooledClass - maintain an instance pool

The two uncommon methods getPooled(), release() are inherited from PooledClass, which provides the instance pooling capacity:

a) if there is no allocated instance (in this case, ReactUpdatesFlushTransaction) in the pool, getPooled() creates a new one;

b) if instances exist in the pool, getPooled() simply returned the instance;

c) release() does not release the instance, instead, it simply put the instance back to the pool.

Like any other kinds of pools, the end purpose of this instance pooling is to reduce the overhead of superfluous resource (in this case, memory) allocation and destruction.

Back to our specific case above:

ReactUpdatesFlushTransaction instances are allocated only when the first time the while loop is executed. After that instances can be obtained through getPooled() from the pool directly.

This level of understanding of PooledClass is sufficient for the rest of this post. So feel free to fast travel to the the next section by ctrl-f “ReactUpdatesFlushTransaction”.

Now we look at its implementation:

1) addPoolingTo() is a “public” method that adds the pooling functionality to a class;

2) oneArgumentPooler() is the getPooled() underlying implementation.

Next we look at addPoolingTo()‘s function body:

1) instancePool is the pool;

2) attach DEFAULT_POOLER (a.k.a., oneArgumentPooler) to the getPooled();

3) set poolSize to 10;

4) attach standardReleaser() to the release().

And this is how getPooled() and release() are implemented:

1) corresponds to b), in which

invokes Klass constructor with the designated parameters (copyFieldsFrom) to initialize the pooling enabled class; and

2) corresponds to a); and

3) corresponds to c).

Last, we look at how addPoolingTo() is used from the outside (ReactUpdatesFlushTransaction):

ReactUpdatesFlushTransaction

1) it is another instantiation of Transaction that overrides the perform() method;

2) instead of calling ReactUpdate.runBatchedUpdates (the callback) directly, the overridden ReactUpdatesFlushTransaction.perform() nest calls another Transaction (ReactReconcileTransaction)’s perform() method and pass method (i.e., ReactUpdate.runBatchedUpdates()) as its callback. Note that ReactReconcileTransaction is also pooling enabled.

3) TRANSACTION_WRAPPERS defines its pre and post-functions:

in which, NESTED_UPDATES‘s initialize() 1.5) stores the number of dirtyComponents; its close() 3) check if the number has changed. If they are different {a} the flushBatchedUpdates() is called to reiterate the process; or {b} it set dirtyComponents.length back to 0, and returns back to the upper level Transaction, ReactDefaultBatchingStrategyTransaction {last post}.

I will not examine the CallbackQueue related operations (in UPDATE_QUEUEING) and will leave them for later articles when discussing component’s life cycle. *9

To recap:

ReactReconcileTransaction

It is another Transaction and nothing is out of ordinary.

1) Its wrappers are defined in TRANSACTION_WRAPPERS;

2) as mentioned before, this class is pooling enabled.

Next we look at its three wrapper:

The comment is quite clear here:

SELECTION_RESTORATION is for storing the focus state of text fields before the UI updating (initialize()), and it restores the state after (close());

EVENT_SUPPRESSION is for storing the toggle state for enabling event, and disable event temporarily before (initialize()), and it restores the state after UI updating (close()).

Again, I will not examine the CallbackQueue related operations (in ON_DOM_READY_QUEUEING) here and will leave them for later articles when discussing component’s life cycle. *10

It is important to note that ReactReconcileTransaction relies on the default Transaction.perform(). Its callback is the ReactUpdate.runBatchedUpdates which is passed all the way down to this level.

ctrl-f “runBatchedUpdates” to examine its route.

And this ReactUpdate.runBatchedUpdates will lead to the content of my next post.

to recap:

Conclusion

That's it. Did I make a serious mistake? or miss out on anything important? Or you simply like the read. Link me on -- I'd be chuffed to hear your feedback.