diff --git a/packages/react-dom/src/events/ReactDOMEventListener.js b/packages/react-dom/src/events/ReactDOMEventListener.js index f228090221ff..f8b8231f8f40 100644 --- a/packages/react-dom/src/events/ReactDOMEventListener.js +++ b/packages/react-dom/src/events/ReactDOMEventListener.js @@ -117,7 +117,7 @@ function dispatchDiscreteEvent( ) { const previousPriority = getCurrentUpdatePriority(); const prevTransition = ReactCurrentBatchConfig.transition; - ReactCurrentBatchConfig.transition = 0; + ReactCurrentBatchConfig.transition = null; try { setCurrentUpdatePriority(DiscreteEventPriority); dispatchEvent(domEventName, eventSystemFlags, container, nativeEvent); @@ -135,7 +135,7 @@ function dispatchContinuousEvent( ) { const previousPriority = getCurrentUpdatePriority(); const prevTransition = ReactCurrentBatchConfig.transition; - ReactCurrentBatchConfig.transition = 0; + ReactCurrentBatchConfig.transition = null; try { setCurrentUpdatePriority(ContinuousEventPriority); dispatchEvent(domEventName, eventSystemFlags, container, nativeEvent); diff --git a/packages/react-reconciler/src/ReactFiberHooks.new.js b/packages/react-reconciler/src/ReactFiberHooks.new.js index 7747a25c858e..6abe576b58fa 100644 --- a/packages/react-reconciler/src/ReactFiberHooks.new.js +++ b/packages/react-reconciler/src/ReactFiberHooks.new.js @@ -1928,7 +1928,7 @@ function mountDeferredValue(value: T): T { const [prevValue, setValue] = mountState(value); mountEffect(() => { const prevTransition = ReactCurrentBatchConfig.transition; - ReactCurrentBatchConfig.transition = 1; + ReactCurrentBatchConfig.transition = {}; try { setValue(value); } finally { @@ -1942,7 +1942,7 @@ function updateDeferredValue(value: T): T { const [prevValue, setValue] = updateState(value); updateEffect(() => { const prevTransition = ReactCurrentBatchConfig.transition; - ReactCurrentBatchConfig.transition = 1; + ReactCurrentBatchConfig.transition = {}; try { setValue(value); } finally { @@ -1956,7 +1956,7 @@ function rerenderDeferredValue(value: T): T { const [prevValue, setValue] = rerenderState(value); updateEffect(() => { const prevTransition = ReactCurrentBatchConfig.transition; - ReactCurrentBatchConfig.transition = 1; + ReactCurrentBatchConfig.transition = {}; try { setValue(value); } finally { @@ -1975,20 +1975,27 @@ function startTransition(setPending, callback) { setPending(true); const prevTransition = ReactCurrentBatchConfig.transition; - ReactCurrentBatchConfig.transition = 1; + ReactCurrentBatchConfig.transition = {}; + const currentTransition = ReactCurrentBatchConfig.transition; + + if (__DEV__) { + ReactCurrentBatchConfig.transition._updatedFibers = new Set(); + } + try { setPending(false); callback(); } finally { setCurrentUpdatePriority(previousPriority); + ReactCurrentBatchConfig.transition = prevTransition; if (__DEV__) { if ( - prevTransition !== 1 && + prevTransition === null && warnOnSubscriptionInsideStartTransition && - ReactCurrentBatchConfig._updatedFibers + currentTransition._updatedFibers ) { - const updatedFibersCount = ReactCurrentBatchConfig._updatedFibers.size; + const updatedFibersCount = currentTransition._updatedFibers.size; if (updatedFibersCount > 10) { console.warn( 'Detected a large number of updates inside startTransition. ' + @@ -1996,7 +2003,7 @@ function startTransition(setPending, callback) { 'Otherwise concurrent mode guarantees are off the table.', ); } - ReactCurrentBatchConfig._updatedFibers.clear(); + currentTransition._updatedFibers.clear(); } } } diff --git a/packages/react-reconciler/src/ReactFiberHooks.old.js b/packages/react-reconciler/src/ReactFiberHooks.old.js index d7137e8cd7f6..cbac3348831f 100644 --- a/packages/react-reconciler/src/ReactFiberHooks.old.js +++ b/packages/react-reconciler/src/ReactFiberHooks.old.js @@ -1928,7 +1928,7 @@ function mountDeferredValue(value: T): T { const [prevValue, setValue] = mountState(value); mountEffect(() => { const prevTransition = ReactCurrentBatchConfig.transition; - ReactCurrentBatchConfig.transition = 1; + ReactCurrentBatchConfig.transition = {}; try { setValue(value); } finally { @@ -1942,7 +1942,7 @@ function updateDeferredValue(value: T): T { const [prevValue, setValue] = updateState(value); updateEffect(() => { const prevTransition = ReactCurrentBatchConfig.transition; - ReactCurrentBatchConfig.transition = 1; + ReactCurrentBatchConfig.transition = {}; try { setValue(value); } finally { @@ -1956,7 +1956,7 @@ function rerenderDeferredValue(value: T): T { const [prevValue, setValue] = rerenderState(value); updateEffect(() => { const prevTransition = ReactCurrentBatchConfig.transition; - ReactCurrentBatchConfig.transition = 1; + ReactCurrentBatchConfig.transition = {}; try { setValue(value); } finally { @@ -1975,20 +1975,27 @@ function startTransition(setPending, callback) { setPending(true); const prevTransition = ReactCurrentBatchConfig.transition; - ReactCurrentBatchConfig.transition = 1; + ReactCurrentBatchConfig.transition = {}; + const currentTransition = ReactCurrentBatchConfig.transition; + + if (__DEV__) { + ReactCurrentBatchConfig.transition._updatedFibers = new Set(); + } + try { setPending(false); callback(); } finally { setCurrentUpdatePriority(previousPriority); + ReactCurrentBatchConfig.transition = prevTransition; if (__DEV__) { if ( - prevTransition !== 1 && + prevTransition === null && warnOnSubscriptionInsideStartTransition && - ReactCurrentBatchConfig._updatedFibers + currentTransition._updatedFibers ) { - const updatedFibersCount = ReactCurrentBatchConfig._updatedFibers.size; + const updatedFibersCount = currentTransition._updatedFibers.size; if (updatedFibersCount > 10) { console.warn( 'Detected a large number of updates inside startTransition. ' + @@ -1996,7 +2003,7 @@ function startTransition(setPending, callback) { 'Otherwise concurrent mode guarantees are off the table.', ); } - ReactCurrentBatchConfig._updatedFibers.clear(); + currentTransition._updatedFibers.clear(); } } } diff --git a/packages/react-reconciler/src/ReactFiberTracingMarkerComponent.new.js b/packages/react-reconciler/src/ReactFiberTracingMarkerComponent.new.js new file mode 100644 index 000000000000..15349ce2d68d --- /dev/null +++ b/packages/react-reconciler/src/ReactFiberTracingMarkerComponent.new.js @@ -0,0 +1,13 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @flow + */ +import type {Fiber} from 'react-reconciler/src/ReactInternalTypes'; + +export type Transition = { + _updatedFibers?: Set, +}; diff --git a/packages/react-reconciler/src/ReactFiberTransition.js b/packages/react-reconciler/src/ReactFiberTransition.js index f154364f8670..d63b99a1862e 100644 --- a/packages/react-reconciler/src/ReactFiberTransition.js +++ b/packages/react-reconciler/src/ReactFiberTransition.js @@ -8,11 +8,12 @@ */ import ReactSharedInternals from 'shared/ReactSharedInternals'; +import type {Transition} from './ReactFiberTracingMarkerComponent.new'; const {ReactCurrentBatchConfig} = ReactSharedInternals; -export const NoTransition = 0; +export const NoTransition = null; -export function requestCurrentTransition(): number { +export function requestCurrentTransition(): Transition | null { return ReactCurrentBatchConfig.transition; } diff --git a/packages/react-reconciler/src/ReactFiberWorkLoop.new.js b/packages/react-reconciler/src/ReactFiberWorkLoop.new.js index 14a313a07774..3b8cf5dcf983 100644 --- a/packages/react-reconciler/src/ReactFiberWorkLoop.new.js +++ b/packages/react-reconciler/src/ReactFiberWorkLoop.new.js @@ -401,9 +401,14 @@ export function requestUpdateLane(fiber: Fiber): Lane { if ( __DEV__ && warnOnSubscriptionInsideStartTransition && - ReactCurrentBatchConfig._updatedFibers + ReactCurrentBatchConfig.transition !== null ) { - ReactCurrentBatchConfig._updatedFibers.add(fiber); + const transition = ReactCurrentBatchConfig.transition; + if (!transition._updatedFibers) { + transition._updatedFibers = new Set(); + } + + transition._updatedFibers.add(fiber); } // The algorithm for assigning an update to a lane should be stable for all // updates at the same priority within the same event. To do this, the @@ -1246,7 +1251,7 @@ export function deferredUpdates(fn: () => A): A { const previousPriority = getCurrentUpdatePriority(); const prevTransition = ReactCurrentBatchConfig.transition; try { - ReactCurrentBatchConfig.transition = 0; + ReactCurrentBatchConfig.transition = null; setCurrentUpdatePriority(DefaultEventPriority); return fn(); } finally { @@ -1285,7 +1290,7 @@ export function discreteUpdates( const previousPriority = getCurrentUpdatePriority(); const prevTransition = ReactCurrentBatchConfig.transition; try { - ReactCurrentBatchConfig.transition = 0; + ReactCurrentBatchConfig.transition = null; setCurrentUpdatePriority(DiscreteEventPriority); return fn(a, b, c, d); } finally { @@ -1320,7 +1325,7 @@ export function flushSync(fn) { const prevTransition = ReactCurrentBatchConfig.transition; const previousPriority = getCurrentUpdatePriority(); try { - ReactCurrentBatchConfig.transition = 0; + ReactCurrentBatchConfig.transition = null; setCurrentUpdatePriority(DiscreteEventPriority); if (fn) { return fn(); @@ -1355,7 +1360,7 @@ export function flushControlled(fn: () => mixed): void { const prevTransition = ReactCurrentBatchConfig.transition; const previousPriority = getCurrentUpdatePriority(); try { - ReactCurrentBatchConfig.transition = 0; + ReactCurrentBatchConfig.transition = null; setCurrentUpdatePriority(DiscreteEventPriority); fn(); } finally { @@ -1893,7 +1898,7 @@ function commitRoot(root: FiberRoot, recoverableErrors: null | Array) { const previousUpdateLanePriority = getCurrentUpdatePriority(); const prevTransition = ReactCurrentBatchConfig.transition; try { - ReactCurrentBatchConfig.transition = 0; + ReactCurrentBatchConfig.transition = null; setCurrentUpdatePriority(DiscreteEventPriority); commitRootImpl(root, recoverableErrors, previousUpdateLanePriority); } finally { @@ -2028,7 +2033,7 @@ function commitRootImpl( if (subtreeHasEffects || rootHasEffect) { const prevTransition = ReactCurrentBatchConfig.transition; - ReactCurrentBatchConfig.transition = 0; + ReactCurrentBatchConfig.transition = null; const previousPriority = getCurrentUpdatePriority(); setCurrentUpdatePriority(DiscreteEventPriority); @@ -2283,7 +2288,7 @@ export function flushPassiveEffects(): boolean { const prevTransition = ReactCurrentBatchConfig.transition; const previousPriority = getCurrentUpdatePriority(); try { - ReactCurrentBatchConfig.transition = 0; + ReactCurrentBatchConfig.transition = null; setCurrentUpdatePriority(priority); return flushPassiveEffectsImpl(); } finally { diff --git a/packages/react-reconciler/src/ReactFiberWorkLoop.old.js b/packages/react-reconciler/src/ReactFiberWorkLoop.old.js index 36e3ba4b943d..ebed3103c885 100644 --- a/packages/react-reconciler/src/ReactFiberWorkLoop.old.js +++ b/packages/react-reconciler/src/ReactFiberWorkLoop.old.js @@ -401,9 +401,14 @@ export function requestUpdateLane(fiber: Fiber): Lane { if ( __DEV__ && warnOnSubscriptionInsideStartTransition && - ReactCurrentBatchConfig._updatedFibers + ReactCurrentBatchConfig.transition !== null ) { - ReactCurrentBatchConfig._updatedFibers.add(fiber); + const transition = ReactCurrentBatchConfig.transition; + if (!transition._updatedFibers) { + transition._updatedFibers = new Set(); + } + + transition._updatedFibers.add(fiber); } // The algorithm for assigning an update to a lane should be stable for all // updates at the same priority within the same event. To do this, the @@ -1246,7 +1251,7 @@ export function deferredUpdates(fn: () => A): A { const previousPriority = getCurrentUpdatePriority(); const prevTransition = ReactCurrentBatchConfig.transition; try { - ReactCurrentBatchConfig.transition = 0; + ReactCurrentBatchConfig.transition = null; setCurrentUpdatePriority(DefaultEventPriority); return fn(); } finally { @@ -1285,7 +1290,7 @@ export function discreteUpdates( const previousPriority = getCurrentUpdatePriority(); const prevTransition = ReactCurrentBatchConfig.transition; try { - ReactCurrentBatchConfig.transition = 0; + ReactCurrentBatchConfig.transition = null; setCurrentUpdatePriority(DiscreteEventPriority); return fn(a, b, c, d); } finally { @@ -1320,7 +1325,7 @@ export function flushSync(fn) { const prevTransition = ReactCurrentBatchConfig.transition; const previousPriority = getCurrentUpdatePriority(); try { - ReactCurrentBatchConfig.transition = 0; + ReactCurrentBatchConfig.transition = null; setCurrentUpdatePriority(DiscreteEventPriority); if (fn) { return fn(); @@ -1355,7 +1360,7 @@ export function flushControlled(fn: () => mixed): void { const prevTransition = ReactCurrentBatchConfig.transition; const previousPriority = getCurrentUpdatePriority(); try { - ReactCurrentBatchConfig.transition = 0; + ReactCurrentBatchConfig.transition = null; setCurrentUpdatePriority(DiscreteEventPriority); fn(); } finally { @@ -1893,7 +1898,7 @@ function commitRoot(root: FiberRoot, recoverableErrors: null | Array) { const previousUpdateLanePriority = getCurrentUpdatePriority(); const prevTransition = ReactCurrentBatchConfig.transition; try { - ReactCurrentBatchConfig.transition = 0; + ReactCurrentBatchConfig.transition = null; setCurrentUpdatePriority(DiscreteEventPriority); commitRootImpl(root, recoverableErrors, previousUpdateLanePriority); } finally { @@ -2028,7 +2033,7 @@ function commitRootImpl( if (subtreeHasEffects || rootHasEffect) { const prevTransition = ReactCurrentBatchConfig.transition; - ReactCurrentBatchConfig.transition = 0; + ReactCurrentBatchConfig.transition = null; const previousPriority = getCurrentUpdatePriority(); setCurrentUpdatePriority(DiscreteEventPriority); @@ -2283,7 +2288,7 @@ export function flushPassiveEffects(): boolean { const prevTransition = ReactCurrentBatchConfig.transition; const previousPriority = getCurrentUpdatePriority(); try { - ReactCurrentBatchConfig.transition = 0; + ReactCurrentBatchConfig.transition = null; setCurrentUpdatePriority(priority); return flushPassiveEffectsImpl(); } finally { diff --git a/packages/react/src/ReactCurrentBatchConfig.js b/packages/react/src/ReactCurrentBatchConfig.js index cca41ae4b349..bf368d6f0b6e 100644 --- a/packages/react/src/ReactCurrentBatchConfig.js +++ b/packages/react/src/ReactCurrentBatchConfig.js @@ -7,22 +7,17 @@ * @flow */ -import type {Fiber} from 'react-reconciler/src/ReactInternalTypes'; +import type {Transition} from 'react-reconciler/src/ReactFiberTracingMarkerComponent.new'; type BatchConfig = { - transition: number, - _updatedFibers?: Set, + transition: Transition | null, }; /** * Keeps track of the current batch's configuration such as how long an update * should suspend for if it needs to. */ const ReactCurrentBatchConfig: BatchConfig = { - transition: 0, + transition: null, }; -if (__DEV__) { - ReactCurrentBatchConfig._updatedFibers = new Set(); -} - export default ReactCurrentBatchConfig; diff --git a/packages/react/src/ReactStartTransition.js b/packages/react/src/ReactStartTransition.js index 3f9c9efe7149..48f9ff96ffa7 100644 --- a/packages/react/src/ReactStartTransition.js +++ b/packages/react/src/ReactStartTransition.js @@ -12,18 +12,24 @@ import {warnOnSubscriptionInsideStartTransition} from 'shared/ReactFeatureFlags' export function startTransition(scope: () => void) { const prevTransition = ReactCurrentBatchConfig.transition; - ReactCurrentBatchConfig.transition = 1; + ReactCurrentBatchConfig.transition = {}; + const currentTransition = ReactCurrentBatchConfig.transition; + + if (__DEV__) { + ReactCurrentBatchConfig.transition._updatedFibers = new Set(); + } try { scope(); } finally { ReactCurrentBatchConfig.transition = prevTransition; + if (__DEV__) { if ( - prevTransition !== 1 && + prevTransition === null && warnOnSubscriptionInsideStartTransition && - ReactCurrentBatchConfig._updatedFibers + currentTransition._updatedFibers ) { - const updatedFibersCount = ReactCurrentBatchConfig._updatedFibers.size; + const updatedFibersCount = currentTransition._updatedFibers.size; if (updatedFibersCount > 10) { console.warn( 'Detected a large number of updates inside startTransition. ' + @@ -31,7 +37,7 @@ export function startTransition(scope: () => void) { 'Otherwise concurrent mode guarantees are off the table.', ); } - ReactCurrentBatchConfig._updatedFibers.clear(); + currentTransition._updatedFibers.clear(); } } }