10
import type {StartTransitionOptions} from 'shared/ReactTypes';
11
12
import ReactCurrentBatchConfig from './ReactCurrentBatchConfig';
13
-import {enableTransitionTracing} from 'shared/ReactFeatureFlags';
13
+import {
14
+ enableAsyncActions,
15
+ enableTransitionTracing,
16
+} from 'shared/ReactFeatureFlags';
17
18
export function startTransition(
19
scope: () => void,
42
}
43
}
44
42
- try {
43
- const returnValue = scope();
44
- callbacks.forEach(callback => callback(currentTransition, returnValue));
45
- } finally {
46
- ReactCurrentBatchConfig.transition = prevTransition;
47
-
48
- if (__DEV__) {
49
- if (prevTransition === null && currentTransition._updatedFibers) {
50
- const updatedFibersCount = currentTransition._updatedFibers.size;
51
- currentTransition._updatedFibers.clear();
52
- if (updatedFibersCount > 10) {
53
- console.warn(
54
- 'Detected a large number of updates inside startTransition. ' +
55
- 'If this is due to a subscription please re-write it to use React provided hooks. ' +
56
- 'Otherwise concurrent mode guarantees are off the table.',
57
- );
58
- }
45
+ if (enableAsyncActions) {
46
+ try {
47
+ const returnValue = scope();
48
+ if (
49
+ typeof returnValue === 'object' &&
50
+ returnValue !== null &&
51
+ typeof returnValue.then === 'function'
52
+ ) {
53
+ callbacks.forEach(callback => callback(currentTransition, returnValue));
54
+ returnValue.then(noop, onError);
55
+ }
56
+ } catch (error) {
57
+ onError(error);
58
+ } finally {
59
+ warnAboutTransitionSubscriptions(prevTransition, currentTransition);
60
+ ReactCurrentBatchConfig.transition = prevTransition;
61
+ }
62
+ } else {
63
+ // When async actions are not enabled, startTransition does not
64
+ // capture errors.
65
+ try {
66
+ scope();
67
+ } finally {
68
+ warnAboutTransitionSubscriptions(prevTransition, currentTransition);
69
+ ReactCurrentBatchConfig.transition = prevTransition;
70
+ }
71
+ }
72
+}
73
+
74
+function warnAboutTransitionSubscriptions(
75
+ prevTransition: BatchConfigTransition | null,
76
+ currentTransition: BatchConfigTransition,
77
+) {
78
+ if (__DEV__) {
79
+ if (prevTransition === null && currentTransition._updatedFibers) {
80
+ const updatedFibersCount = currentTransition._updatedFibers.size;
81
+ currentTransition._updatedFibers.clear();
82
+ if (updatedFibersCount > 10) {
83
+ console.warn(
84
+ 'Detected a large number of updates inside startTransition. ' +
85
+ 'If this is due to a subscription please re-write it to use React provided hooks. ' +
86
+ 'Otherwise concurrent mode guarantees are off the table.',
87
+ );
88
}
89
}
90
}
91
}
92
+
93
+function noop() {}
94
+
95
+// Use reportError, if it exists. Otherwise console.error. This is the same as
96
+// the default for onRecoverableError.
97
+const onError =
98
+ typeof reportError === 'function'
99
+ ? // In modern browsers, reportError will dispatch an error event,
100
+ // emulating an uncaught JavaScript error.
101
+ reportError
102
+ : (error: mixed) => {
103
+ // In older browsers and test environments, fallback to console.error.
104
+ // eslint-disable-next-line react-internal/no-production-logging
105
+ console['error'](error);
106
+ };