import type {BatchConfigTransition} from 'react-reconciler/src/ReactFiberTracingMarkerComponent';
import type {StartTransitionOptions} from 'shared/ReactTypes';
import ReactCurrentBatchConfig from './ReactCurrentBatchConfig';
import {
enableAsyncActions,
enableTransitionTracing,
} from 'shared/ReactFeatureFlags';
import reportGlobalError from 'shared/reportGlobalError';
export function startTransition(
scope: () => void,
options?: StartTransitionOptions,
) {
const prevTransition = ReactCurrentBatchConfig.transition;
const callbacks = new Set<(BatchConfigTransition, mixed) => mixed>();
const transition: BatchConfigTransition = {
_callbacks: callbacks,
};
ReactCurrentBatchConfig.transition = transition;
const currentTransition = ReactCurrentBatchConfig.transition;
if (__DEV__) {
ReactCurrentBatchConfig.transition._updatedFibers = new Set();
}
if (enableTransitionTracing) {
if (options !== undefined && options.name !== undefined) {
ReactCurrentBatchConfig.transition.name = options.name;
ReactCurrentBatchConfig.transition.startTime = -1;
}
}
if (enableAsyncActions) {
try {
const returnValue = scope();
if (
typeof returnValue === 'object' &&
returnValue !== null &&
typeof returnValue.then === 'function'
) {
callbacks.forEach(callback => callback(currentTransition, returnValue));
returnValue.then(noop, reportGlobalError);
}
} catch (error) {
reportGlobalError(error);
} finally {
warnAboutTransitionSubscriptions(prevTransition, currentTransition);
ReactCurrentBatchConfig.transition = prevTransition;
}
} else {
try {
scope();
} finally {
warnAboutTransitionSubscriptions(prevTransition, currentTransition);
ReactCurrentBatchConfig.transition = prevTransition;
}
}
}
function warnAboutTransitionSubscriptions(
prevTransition: BatchConfigTransition | null,
currentTransition: BatchConfigTransition,
) {
if (__DEV__) {
if (prevTransition === null && currentTransition._updatedFibers) {
const updatedFibersCount = currentTransition._updatedFibers.size;
currentTransition._updatedFibers.clear();
if (updatedFibersCount > 10) {
console.warn(
'Detected a large number of updates inside startTransition. ' +
'If this is due to a subscription please re-write it to use React provided hooks. ' +
'Otherwise concurrent mode guarantees are off the table.',
);
}
}
}
}
function noop() {}