var ReactUpdates = { /** * React references `ReactReconcileTransaction` using this property in order * to allow dependency injection. * * @internal */ ReactReconcileTransaction: null,
// 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 setState, forceUpdate, etc.; creation and // destruction of top-level components is guarded in ReactMount.)
if (!batchingStrategy.isBatchingUpdates) { batchingStrategy.batchedUpdates(enqueueUpdate, component); return; }
var flushBatchedUpdates = function() { // ReactUpdatesFlushTransaction's wrappers will clear the dirtyComponents // array and perform any updates enqueued by mount-ready handlers (i.e., // componentDidUpdate) but we need to check here too in order to catch // updates enqueued by setState callbacks and asap calls. while (dirtyComponents.length || asapEnqueued) { if (dirtyComponents.length) { var transaction = ReactUpdatesFlushTransaction.getPooled(); transaction.perform(runBatchedUpdates, null, transaction); ReactUpdatesFlushTransaction.release(transaction); }
if (asapEnqueued) { asapEnqueued = false; var queue = asapCallbackQueue; asapCallbackQueue = CallbackQueue.getPooled(); queue.notifyAll(); CallbackQueue.release(queue); } } };
var NESTED_UPDATES = { initialize: function() { this.dirtyComponentsLength = dirtyComponents.length; }, close: function() { if (this.dirtyComponentsLength !== dirtyComponents.length) { // Additional updates were enqueued by componentDidUpdate handlers or // similar; before our own UPDATE_QUEUEING wrapper closes, we want to run // these new updates so that if A's componentDidUpdate calls setState on // B, B will update before the callback A's updater provided when calling // setState. dirtyComponents.splice(0, this.dirtyComponentsLength); flushBatchedUpdates(); } else { dirtyComponents.length = 0; } }, };
functionrunBatchedUpdates(transaction) { var len = transaction.dirtyComponentsLength; invariant( len === dirtyComponents.length, "Expected flush transaction's stored dirty-components length (%s) to " + 'match dirty-components array length (%s).', len, dirtyComponents.length, );
// Since reconciling a component higher in the owner hierarchy usually (not // always -- see shouldComponentUpdate()) will reconcile children, reconcile // them before their children by sorting the array. dirtyComponents.sort(mountOrderComparator);
// 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). updateBatchNumber++;
for (var i = 0; i < len; i++) { // If a component is unmounted before pending changes apply, it will still // be here, but we assume that it has cleared its _pendingCallbacks and // that performUpdateIfNecessary is a noop. var component = dirtyComponents[i];
// If performUpdateIfNecessary happens to enqueue any new updates, we // shouldn't execute the callbacks until the next render happens, so // stash the callbacks first var callbacks = component._pendingCallbacks; component._pendingCallbacks = null;
var markerName; if (ReactFeatureFlags.logTopLevelRenders) { var namedComponent = component; // Duck type TopLevelWrapper. This is probably always true. if (component._currentElement.type.isReactTopLevelWrapper) { namedComponent = component._renderedComponent; } markerName = 'React update: ' + namedComponent.getName(); console.time(markerName); }
// 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 setState, forceUpdate, etc.; creation and // destruction of top-level components is guarded in ReactMount.)
if (!batchingStrategy.isBatchingUpdates) { batchingStrategy.batchedUpdates(enqueueUpdate, component); return; }