10.0 Part 10 (clickable)
As you can see, React loop through dirtyComponents
(1), and call ReactUpdates.runBatchedUpdates
(2), through transaction! Transaction? The new one, but why? Let’s see.
The transaction type is ReactUpdatesFlushTransaction
and, we’ve already mentioned that before, we need to check wrappers
to understand what the transaction actually does. A small hint from the code comment:
‘ReactUpdatesFlushTransaction's wrappers will clear the dirtyComponents array and perform any updates enqueued by mount-ready handlers (i.e., componentDidUpdate)’
But, anyway, we need to prove that. There are two wrappers NESTED_UPDATES
and UPDATE_QUEUEING
. On initialize
phase we store dirtyComponentsLength
(3) and, as you can check on close
, React compares, maybe during updates a flush number of dirty components was changed, so, obviously it’s needed to run flushBatchedUpdates
one more time. You see, no magic, everything is pretty straightforward.
Well.. one magic moment actually is present. ReactUpdatesFlushTransaction
overrides Transaction.perform
method, because… it actually requires behavior from ReactReconcileTransaction
(transaction is used during mounting and allows to keep app state safe). So, inside ReactUpdatesFlushTransaction.perform
method, ReactReconcileTransaction
is used as well, so transaction method actually is wrapped one more time.
So, technically, it looks like:
[NESTED_UPDATES, UPDATE_QUEUEING].initialize()
[SELECTION_RESTORATION, EVENT_SUPPRESSION, ON_DOM_READY_QUEUEING].initialize()
method -> ReactUpdates.runBatchedUpdates
[SELECTION_RESTORATION, EVENT_SUPPRESSION, ON_DOM_READY_QUEUEING].close()
[NESTED_UPDATES, UPDATE_QUEUEING].close()
We will go back to the transaction in the end, to double check how it helps to finish method work, but now, let’s see details of ReactUpdates.runBatchedUpdates
(2) (\src\renderers\shared\stack\reconciler\ReactUpdates.js#125
)
The first thing we should do from the very beginning - sort dirtyComponets
array (4). How to sort? By mount order
(integer number was set to a component when instance mounted), it means that parents (they were mounted first) will be updated first, children next, and so on.
The next step, we increase updateBatchNumber
, it’s something like ID for current reconciling. According to comment in the code:
‘Any updates enqueued while reconciling must be performed after this entire batch. Otherwise, if dirtyComponents is [A, B] where A has children B and C, B could update twice in a single batch if C's render enqueues an update to B (since B would have already updated, we should skip it, and the only way we can know to do so is by checking the batch counter).’
It helps actually to avoid double updates for the same components.
Well done, finally we loop through dirtyComponents
and pass each component to ReactReconciler.performUpdateIfNecessary
(5), where actually performUpdateIfNecessary
method will be called from ReactCompositeComponent
instance, so, move on to ReactCompositeComponent
code again and its method updateComponent
. Here we can find something interesting for us, so, let’s dive deeper.
Let’s recap how we got here. Let's look at the scheme one more time, then remove redundant less important pieces, and it becomes this:
10.1 Part 10 simplified (clickable)
And we should probably fix spaces and alignment as well:
10.2 Part 10 simplified & refactored (clickable)
Nice. In fact, that’s all that happens here. So, we can take the essential value from Part 10 and use it for the final updating
scheme:
10.3 Part 10 essential value (clickable)
And then we're done!