diff --git a/src/renderers/dom/fiber/ReactDOMFiber.js b/src/renderers/dom/fiber/ReactDOMFiber.js index ca3b1f703b309..6d59e5aed7821 100644 --- a/src/renderers/dom/fiber/ReactDOMFiber.js +++ b/src/renderers/dom/fiber/ReactDOMFiber.js @@ -165,6 +165,10 @@ var ReactDOM = { return DOMRenderer.findHostInstance(component); }, + unstable_batchedUpdates(fn : Function) : void { + DOMRenderer.batchedUpdates(fn); + }, + }; module.exports = ReactDOM; diff --git a/src/renderers/shared/fiber/ReactFiberReconciler.js b/src/renderers/shared/fiber/ReactFiberReconciler.js index d86c4946d4ed0..f14559dfa806b 100644 --- a/src/renderers/shared/fiber/ReactFiberReconciler.js +++ b/src/renderers/shared/fiber/ReactFiberReconciler.js @@ -68,6 +68,7 @@ export type Reconciler = { updateContainer(element : ReactElement, container : OpaqueNode) : void, unmountContainer(container : OpaqueNode) : void, performWithPriority(priorityLevel : PriorityLevel, fn : Function) : void, + batchedUpdates(fn: Function) : void, // Used to extract the return value from the initial render. Legacy API. getPublicRootInstance(container : OpaqueNode) : (ReactComponent | TI | I | null), @@ -78,7 +79,11 @@ export type Reconciler = { module.exports = function(config : HostConfig) : Reconciler { - var { scheduleWork, performWithPriority } = ReactFiberScheduler(config); + var { + scheduleWork, + performWithPriority, + batchedUpdates, + } = ReactFiberScheduler(config); return { @@ -142,6 +147,8 @@ module.exports = function(config : HostConfig) : performWithPriority, + batchedUpdates, + getPublicRootInstance(container : OpaqueNode) : (ReactComponent | I | TI | null) { const root : FiberRoot = (container.stateNode : any); const containerFiber = root.current; diff --git a/src/renderers/shared/fiber/ReactFiberScheduler.js b/src/renderers/shared/fiber/ReactFiberScheduler.js index f93a849bc61c3..8029788794496 100644 --- a/src/renderers/shared/fiber/ReactFiberScheduler.js +++ b/src/renderers/shared/fiber/ReactFiberScheduler.js @@ -508,12 +508,10 @@ module.exports = function(config : HostConfig) { } function performSynchronousWork() { - if (useSyncScheduling) { - // Start batching updates - shouldBatchUpdates = true; - } - performAndHandleErrors(performSynchronousWorkUnsafe); - shouldBatchUpdates = false; + // All nested updates are batched + batchedUpdates(() => { + performAndHandleErrors(performSynchronousWorkUnsafe); + }); } function scheduleSynchronousWork(root : FiberRoot) { @@ -534,6 +532,7 @@ module.exports = function(config : HostConfig) { lastScheduledRoot = root; if (!shouldBatchUpdates) { + // Unless in batched mode, perform work immediately performSynchronousWork(); } } @@ -690,9 +689,20 @@ module.exports = function(config : HostConfig) { } } + function batchedUpdates(fn: Function) { + const prev = shouldBatchUpdates; + shouldBatchUpdates = true; + try { + fn(); + } finally { + shouldBatchUpdates = prev; + } + } + return { scheduleWork: scheduleWork, scheduleDeferredWork: scheduleDeferredWork, performWithPriority: performWithPriority, + batchedUpdates: batchedUpdates, }; };