Skip to content

Commit 7795b3e

Browse files
author
Brian Vaughn
committed
Revert "Replace flushDiscreteUpdates with flushSync (facebook#21775)"
This reverts commit 32eefcb.
1 parent 62bd6d7 commit 7795b3e

11 files changed

+99
-73
lines changed

packages/react-dom/src/__tests__/ReactDOMFiber-test.js

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1154,13 +1154,19 @@ describe('ReactDOMFiber', () => {
11541154
expect(ops).toEqual(['A']);
11551155

11561156
if (__DEV__) {
1157-
expect(console.error.calls.count()).toBe(2);
1157+
const errorCalls = console.error.calls.count();
11581158
expect(console.error.calls.argsFor(0)[0]).toMatch(
11591159
'ReactDOM.render is no longer supported in React 18',
11601160
);
11611161
expect(console.error.calls.argsFor(1)[0]).toMatch(
11621162
'ReactDOM.render is no longer supported in React 18',
11631163
);
1164+
// TODO: this warning shouldn't be firing in the first place if user didn't call it.
1165+
for (let i = 2; i < errorCalls; i++) {
1166+
expect(console.error.calls.argsFor(i)[0]).toMatch(
1167+
'unstable_flushDiscreteUpdates: Cannot flush updates when React is already rendering.',
1168+
);
1169+
}
11641170
}
11651171
});
11661172

packages/react-dom/src/client/ReactDOM.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@ import {createEventHandle} from './ReactDOMEventHandle';
2323
import {
2424
batchedUpdates,
2525
discreteUpdates,
26+
flushDiscreteUpdates,
2627
flushSync,
27-
flushSyncWithoutWarningIfAlreadyRendering,
2828
flushControlled,
2929
injectIntoDevTools,
3030
attemptSynchronousHydration,
@@ -100,7 +100,7 @@ setRestoreImplementation(restoreControlledState);
100100
setBatchingImplementation(
101101
batchedUpdates,
102102
discreteUpdates,
103-
flushSyncWithoutWarningIfAlreadyRendering,
103+
flushDiscreteUpdates,
104104
);
105105

106106
function createPortal(

packages/react-dom/src/events/ReactDOMUpdateBatching.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ let batchedUpdatesImpl = function(fn, bookkeeping) {
2323
let discreteUpdatesImpl = function(fn, a, b, c, d) {
2424
return fn(a, b, c, d);
2525
};
26-
let flushSyncImpl = function() {};
26+
let flushDiscreteUpdatesImpl = function() {};
2727

2828
let isInsideEventHandler = false;
2929

@@ -39,7 +39,7 @@ function finishEventHandler() {
3939
// bails out of the update without touching the DOM.
4040
// TODO: Restore state in the microtask, after the discrete updates flush,
4141
// instead of early flushing them here.
42-
flushSyncImpl();
42+
flushDiscreteUpdatesImpl();
4343
restoreStateIfNeeded();
4444
}
4545
}
@@ -67,9 +67,9 @@ export function discreteUpdates(fn, a, b, c, d) {
6767
export function setBatchingImplementation(
6868
_batchedUpdatesImpl,
6969
_discreteUpdatesImpl,
70-
_flushSyncImpl,
70+
_flushDiscreteUpdatesImpl,
7171
) {
7272
batchedUpdatesImpl = _batchedUpdatesImpl;
7373
discreteUpdatesImpl = _discreteUpdatesImpl;
74-
flushSyncImpl = _flushSyncImpl;
74+
flushDiscreteUpdatesImpl = _flushDiscreteUpdatesImpl;
7575
}

packages/react-noop-renderer/src/ReactNoop.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ export const {
4141
unbatchedUpdates,
4242
discreteUpdates,
4343
idleUpdates,
44+
flushDiscreteUpdates,
4445
flushSync,
4546
flushPassiveEffects,
4647
act,

packages/react-noop-renderer/src/createReactNoop.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -915,6 +915,8 @@ function createReactNoop(reconciler: Function, useMutation: boolean) {
915915
}
916916
},
917917

918+
flushDiscreteUpdates: NoopRenderer.flushDiscreteUpdates,
919+
918920
flushSync(fn: () => mixed) {
919921
NoopRenderer.flushSync(fn);
920922
},

packages/react-reconciler/src/ReactFiberReconciler.js

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,9 @@ import {
2121
unbatchedUpdates as unbatchedUpdates_old,
2222
deferredUpdates as deferredUpdates_old,
2323
discreteUpdates as discreteUpdates_old,
24+
flushDiscreteUpdates as flushDiscreteUpdates_old,
2425
flushControlled as flushControlled_old,
2526
flushSync as flushSync_old,
26-
flushSyncWithoutWarningIfAlreadyRendering as flushSyncWithoutWarningIfAlreadyRendering_old,
2727
flushPassiveEffects as flushPassiveEffects_old,
2828
getPublicRootInstance as getPublicRootInstance_old,
2929
attemptSynchronousHydration as attemptSynchronousHydration_old,
@@ -59,9 +59,9 @@ import {
5959
unbatchedUpdates as unbatchedUpdates_new,
6060
deferredUpdates as deferredUpdates_new,
6161
discreteUpdates as discreteUpdates_new,
62+
flushDiscreteUpdates as flushDiscreteUpdates_new,
6263
flushControlled as flushControlled_new,
6364
flushSync as flushSync_new,
64-
flushSyncWithoutWarningIfAlreadyRendering as flushSyncWithoutWarningIfAlreadyRendering_new,
6565
flushPassiveEffects as flushPassiveEffects_new,
6666
getPublicRootInstance as getPublicRootInstance_new,
6767
attemptSynchronousHydration as attemptSynchronousHydration_new,
@@ -108,13 +108,13 @@ export const deferredUpdates = enableNewReconciler
108108
export const discreteUpdates = enableNewReconciler
109109
? discreteUpdates_new
110110
: discreteUpdates_old;
111+
export const flushDiscreteUpdates = enableNewReconciler
112+
? flushDiscreteUpdates_new
113+
: flushDiscreteUpdates_old;
111114
export const flushControlled = enableNewReconciler
112115
? flushControlled_new
113116
: flushControlled_old;
114117
export const flushSync = enableNewReconciler ? flushSync_new : flushSync_old;
115-
export const flushSyncWithoutWarningIfAlreadyRendering = enableNewReconciler
116-
? flushSyncWithoutWarningIfAlreadyRendering_new
117-
: flushSyncWithoutWarningIfAlreadyRendering_old;
118118
export const flushPassiveEffects = enableNewReconciler
119119
? flushPassiveEffects_new
120120
: flushPassiveEffects_old;

packages/react-reconciler/src/ReactFiberReconciler.new.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ import {
5757
flushControlled,
5858
deferredUpdates,
5959
discreteUpdates,
60-
flushSyncWithoutWarningIfAlreadyRendering,
60+
flushDiscreteUpdates,
6161
flushPassiveEffects,
6262
} from './ReactFiberWorkLoop.new';
6363
import {
@@ -330,9 +330,9 @@ export {
330330
unbatchedUpdates,
331331
deferredUpdates,
332332
discreteUpdates,
333+
flushDiscreteUpdates,
333334
flushControlled,
334335
flushSync,
335-
flushSyncWithoutWarningIfAlreadyRendering,
336336
flushPassiveEffects,
337337
};
338338

packages/react-reconciler/src/ReactFiberReconciler.old.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ import {
5757
flushControlled,
5858
deferredUpdates,
5959
discreteUpdates,
60-
flushSyncWithoutWarningIfAlreadyRendering,
60+
flushDiscreteUpdates,
6161
flushPassiveEffects,
6262
} from './ReactFiberWorkLoop.old';
6363
import {
@@ -330,9 +330,9 @@ export {
330330
unbatchedUpdates,
331331
deferredUpdates,
332332
discreteUpdates,
333+
flushDiscreteUpdates,
333334
flushControlled,
334335
flushSync,
335-
flushSyncWithoutWarningIfAlreadyRendering,
336336
flushPassiveEffects,
337337
};
338338

packages/react-reconciler/src/ReactFiberWorkLoop.new.js

Lines changed: 37 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1044,6 +1044,34 @@ export function getExecutionContext(): ExecutionContext {
10441044
return executionContext;
10451045
}
10461046

1047+
export function flushDiscreteUpdates() {
1048+
// TODO: Should be able to flush inside batchedUpdates, but not inside `act`.
1049+
// However, `act` uses `batchedUpdates`, so there's no way to distinguish
1050+
// those two cases. Need to fix this before exposing flushDiscreteUpdates
1051+
// as a public API.
1052+
if (
1053+
(executionContext & (BatchedContext | RenderContext | CommitContext)) !==
1054+
NoContext
1055+
) {
1056+
if (__DEV__) {
1057+
if ((executionContext & RenderContext) !== NoContext) {
1058+
console.error(
1059+
'unstable_flushDiscreteUpdates: Cannot flush updates when React is ' +
1060+
'already rendering.',
1061+
);
1062+
}
1063+
}
1064+
// We're already rendering, so we can't synchronously flush pending work.
1065+
// This is probably a nested event dispatch triggered by a lifecycle/effect,
1066+
// like `el.focus()`. Exit.
1067+
return;
1068+
}
1069+
flushSyncCallbacks();
1070+
// If the discrete updates scheduled passive effects, flush them now so that
1071+
// they fire before the next serial event.
1072+
flushPassiveEffects();
1073+
}
1074+
10471075
export function deferredUpdates<A>(fn: () => A): A {
10481076
const previousPriority = getCurrentUpdatePriority();
10491077
const prevTransition = ReactCurrentBatchConfig.transition;
@@ -1114,10 +1142,7 @@ export function unbatchedUpdates<A, R>(fn: (a: A) => R, a: A): R {
11141142
}
11151143
}
11161144

1117-
export function flushSyncWithoutWarningIfAlreadyRendering<A, R>(
1118-
fn: A => R,
1119-
a: A,
1120-
): R {
1145+
export function flushSync<A, R>(fn: A => R, a: A): R {
11211146
const prevExecutionContext = executionContext;
11221147
executionContext |= BatchedContext;
11231148

@@ -1140,23 +1165,18 @@ export function flushSyncWithoutWarningIfAlreadyRendering<A, R>(
11401165
// the stack.
11411166
if ((executionContext & (RenderContext | CommitContext)) === NoContext) {
11421167
flushSyncCallbacks();
1168+
} else {
1169+
if (__DEV__) {
1170+
console.error(
1171+
'flushSync was called from inside a lifecycle method. React cannot ' +
1172+
'flush when React is already rendering. Consider moving this call to ' +
1173+
'a scheduler task or micro task.',
1174+
);
1175+
}
11431176
}
11441177
}
11451178
}
11461179

1147-
export function flushSync<A, R>(fn: A => R, a: A): R {
1148-
if (__DEV__) {
1149-
if ((executionContext & (RenderContext | CommitContext)) !== NoContext) {
1150-
console.error(
1151-
'flushSync was called from inside a lifecycle method. React cannot ' +
1152-
'flush when React is already rendering. Consider moving this call to ' +
1153-
'a scheduler task or micro task.',
1154-
);
1155-
}
1156-
}
1157-
return flushSyncWithoutWarningIfAlreadyRendering(fn, a);
1158-
}
1159-
11601180
export function flushControlled(fn: () => mixed): void {
11611181
const prevExecutionContext = executionContext;
11621182
executionContext |= BatchedContext;

packages/react-reconciler/src/ReactFiberWorkLoop.old.js

Lines changed: 37 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1044,6 +1044,34 @@ export function getExecutionContext(): ExecutionContext {
10441044
return executionContext;
10451045
}
10461046

1047+
export function flushDiscreteUpdates() {
1048+
// TODO: Should be able to flush inside batchedUpdates, but not inside `act`.
1049+
// However, `act` uses `batchedUpdates`, so there's no way to distinguish
1050+
// those two cases. Need to fix this before exposing flushDiscreteUpdates
1051+
// as a public API.
1052+
if (
1053+
(executionContext & (BatchedContext | RenderContext | CommitContext)) !==
1054+
NoContext
1055+
) {
1056+
if (__DEV__) {
1057+
if ((executionContext & RenderContext) !== NoContext) {
1058+
console.error(
1059+
'unstable_flushDiscreteUpdates: Cannot flush updates when React is ' +
1060+
'already rendering.',
1061+
);
1062+
}
1063+
}
1064+
// We're already rendering, so we can't synchronously flush pending work.
1065+
// This is probably a nested event dispatch triggered by a lifecycle/effect,
1066+
// like `el.focus()`. Exit.
1067+
return;
1068+
}
1069+
flushSyncCallbacks();
1070+
// If the discrete updates scheduled passive effects, flush them now so that
1071+
// they fire before the next serial event.
1072+
flushPassiveEffects();
1073+
}
1074+
10471075
export function deferredUpdates<A>(fn: () => A): A {
10481076
const previousPriority = getCurrentUpdatePriority();
10491077
const prevTransition = ReactCurrentBatchConfig.transition;
@@ -1114,10 +1142,7 @@ export function unbatchedUpdates<A, R>(fn: (a: A) => R, a: A): R {
11141142
}
11151143
}
11161144

1117-
export function flushSyncWithoutWarningIfAlreadyRendering<A, R>(
1118-
fn: A => R,
1119-
a: A,
1120-
): R {
1145+
export function flushSync<A, R>(fn: A => R, a: A): R {
11211146
const prevExecutionContext = executionContext;
11221147
executionContext |= BatchedContext;
11231148

@@ -1140,23 +1165,18 @@ export function flushSyncWithoutWarningIfAlreadyRendering<A, R>(
11401165
// the stack.
11411166
if ((executionContext & (RenderContext | CommitContext)) === NoContext) {
11421167
flushSyncCallbacks();
1168+
} else {
1169+
if (__DEV__) {
1170+
console.error(
1171+
'flushSync was called from inside a lifecycle method. React cannot ' +
1172+
'flush when React is already rendering. Consider moving this call to ' +
1173+
'a scheduler task or micro task.',
1174+
);
1175+
}
11431176
}
11441177
}
11451178
}
11461179

1147-
export function flushSync<A, R>(fn: A => R, a: A): R {
1148-
if (__DEV__) {
1149-
if ((executionContext & (RenderContext | CommitContext)) !== NoContext) {
1150-
console.error(
1151-
'flushSync was called from inside a lifecycle method. React cannot ' +
1152-
'flush when React is already rendering. Consider moving this call to ' +
1153-
'a scheduler task or micro task.',
1154-
);
1155-
}
1156-
}
1157-
return flushSyncWithoutWarningIfAlreadyRendering(fn, a);
1158-
}
1159-
11601180
export function flushControlled(fn: () => mixed): void {
11611181
const prevExecutionContext = executionContext;
11621182
executionContext |= BatchedContext;

packages/react-reconciler/src/__tests__/ReactFlushSync-test.js

Lines changed: 0 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -173,27 +173,4 @@ describe('ReactFlushSync', () => {
173173
// Effect flushes after paint.
174174
expect(Scheduler).toHaveYielded(['Effect']);
175175
});
176-
177-
test('does not flush pending passive effects', async () => {
178-
function App() {
179-
useEffect(() => {
180-
Scheduler.unstable_yieldValue('Effect');
181-
}, []);
182-
return <Text text="Child" />;
183-
}
184-
185-
const root = ReactNoop.createRoot();
186-
await act(async () => {
187-
root.render(<App />);
188-
expect(Scheduler).toFlushUntilNextPaint(['Child']);
189-
expect(root).toMatchRenderedOutput('Child');
190-
191-
// Passive effects are pending. Calling flushSync should not affect them.
192-
ReactNoop.flushSync();
193-
// Effects still haven't fired.
194-
expect(Scheduler).toHaveYielded([]);
195-
});
196-
// Now the effects have fired.
197-
expect(Scheduler).toHaveYielded(['Effect']);
198-
});
199176
});

0 commit comments

Comments
 (0)