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 Transaction
s which, together with ReactDefaultBatchingStrategyTransaction
, outline the UI updating processing logic.
Files used in this article:
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}.
1 | ... |
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:
1 | ... |
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 | var PooledClass = { |
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 | ... |
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 | var oneArgumentPooler = function(copyFieldsFrom) { |
1) corresponds to b), in which
1 | Klass.call(instance, copyFieldsFrom); |
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
):
1 | ... |
ReactUpdatesFlushTransaction
1 | ... |
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:
1 | ... |
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 (inUPDATE_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 | var Mixin = { |
1) Its wrappers are defined in TRANSACTION_WRAPPERS
;
2) as mentioned before, this class is pooling enabled.
Next we look at its three wrapper:
1 | /** |
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 (inON_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: