diff --git a/packages/react-dom/index.classic.fb.js b/packages/react-dom/index.classic.fb.js
index e946df7b76db6..1264badae76ca 100644
--- a/packages/react-dom/index.classic.fb.js
+++ b/packages/react-dom/index.classic.fb.js
@@ -30,8 +30,6 @@ export {
unmountComponentAtNode,
createRoot,
createBlockingRoot,
- unstable_discreteUpdates,
- unstable_flushDiscreteUpdates,
unstable_flushControlled,
unstable_scheduleHydration,
unstable_renderSubtreeIntoContainer,
diff --git a/packages/react-dom/index.experimental.js b/packages/react-dom/index.experimental.js
index b771d0105b8e5..40676689ee282 100644
--- a/packages/react-dom/index.experimental.js
+++ b/packages/react-dom/index.experimental.js
@@ -21,8 +21,6 @@ export {
// exposeConcurrentModeAPIs
createRoot,
createBlockingRoot,
- unstable_discreteUpdates,
- unstable_flushDiscreteUpdates,
unstable_flushControlled,
unstable_scheduleHydration,
// Disabled behind disableUnstableRenderSubtreeIntoContainer
diff --git a/packages/react-dom/index.modern.fb.js b/packages/react-dom/index.modern.fb.js
index bcb213ad4ee35..258e12303ec11 100644
--- a/packages/react-dom/index.modern.fb.js
+++ b/packages/react-dom/index.modern.fb.js
@@ -15,8 +15,6 @@ export {
version,
createRoot,
createBlockingRoot,
- unstable_discreteUpdates,
- unstable_flushDiscreteUpdates,
unstable_flushControlled,
unstable_scheduleHydration,
} from './src/client/ReactDOM';
diff --git a/packages/react-dom/src/client/ReactDOM.js b/packages/react-dom/src/client/ReactDOM.js
index ee294218ced49..741d24f731815 100644
--- a/packages/react-dom/src/client/ReactDOM.js
+++ b/packages/react-dom/src/client/ReactDOM.js
@@ -200,8 +200,6 @@ export {
// exposeConcurrentModeAPIs
createRoot,
createBlockingRoot,
- discreteUpdates as unstable_discreteUpdates,
- flushDiscreteUpdates as unstable_flushDiscreteUpdates,
flushControlled as unstable_flushControlled,
scheduleHydration as unstable_scheduleHydration,
// Disabled behind disableUnstableRenderSubtreeIntoContainer
diff --git a/packages/react-interactions/events/src/dom/__tests__/MixedResponders-test-internal.js b/packages/react-interactions/events/src/dom/__tests__/MixedResponders-test-internal.js
index 2a31c5f37f210..614aaffc1b7cf 100644
--- a/packages/react-interactions/events/src/dom/__tests__/MixedResponders-test-internal.js
+++ b/packages/react-interactions/events/src/dom/__tests__/MixedResponders-test-internal.js
@@ -104,76 +104,6 @@ describe('mixing responders with the heritage event system', () => {
document.body.removeChild(newContainer);
});
- // @gate experimental
- it('should properly flush sync when the event systems are mixed with unstable_flushDiscreteUpdates', () => {
- const useTap = require('react-interactions/events/tap').useTap;
- const ref = React.createRef();
- let renderCounts = 0;
-
- function MyComponent() {
- const [, updateCounter] = React.useState(0);
- renderCounts++;
-
- function handleTap() {
- updateCounter(count => count + 1);
- }
-
- const listener = useTap({
- onTapEnd: handleTap,
- });
-
- return (
-
-
-
- );
- }
-
- const newContainer = document.createElement('div');
- const root = ReactDOM.createRoot(newContainer);
- document.body.appendChild(newContainer);
- root.render();
- Scheduler.unstable_flushAll();
-
- const target = createEventTarget(ref.current);
- target.pointerdown({timeStamp: 100});
- target.pointerup({timeStamp: 100});
-
- if (__DEV__) {
- expect(renderCounts).toBe(4);
- } else {
- expect(renderCounts).toBe(2);
- }
- Scheduler.unstable_flushAll();
- if (__DEV__) {
- expect(renderCounts).toBe(6);
- } else {
- expect(renderCounts).toBe(3);
- }
-
- target.pointerdown({timeStamp: 100});
- // Ensure the timeStamp logic works
- target.pointerup({timeStamp: 101});
-
- if (__DEV__) {
- expect(renderCounts).toBe(8);
- } else {
- expect(renderCounts).toBe(4);
- }
-
- Scheduler.unstable_flushAll();
- document.body.removeChild(newContainer);
- });
-
// @gate experimental
it(
'should only flush before outermost discrete event handler when mixing ' +
diff --git a/packages/react-reconciler/src/ReactFiberHotReloading.new.js b/packages/react-reconciler/src/ReactFiberHotReloading.new.js
index 21819bf9edbc1..0fe04f2cc9db6 100644
--- a/packages/react-reconciler/src/ReactFiberHotReloading.new.js
+++ b/packages/react-reconciler/src/ReactFiberHotReloading.new.js
@@ -18,7 +18,7 @@ import {
scheduleUpdateOnFiber,
flushPassiveEffects,
} from './ReactFiberWorkLoop.new';
-import {updateContainer, syncUpdates} from './ReactFiberReconciler.new';
+import {updateContainer} from './ReactFiberReconciler.new';
import {emptyContextObject} from './ReactFiberContext.new';
import {SyncLane} from './ReactFiberLane';
import {
@@ -258,7 +258,7 @@ export const scheduleRoot: ScheduleRoot = (
return;
}
flushPassiveEffects();
- syncUpdates(() => {
+ flushSync(() => {
updateContainer(element, root, null, null);
});
}
diff --git a/packages/react-reconciler/src/ReactFiberHotReloading.old.js b/packages/react-reconciler/src/ReactFiberHotReloading.old.js
index 4e2951b7d4a54..6796db9511065 100644
--- a/packages/react-reconciler/src/ReactFiberHotReloading.old.js
+++ b/packages/react-reconciler/src/ReactFiberHotReloading.old.js
@@ -18,7 +18,7 @@ import {
scheduleUpdateOnFiber,
flushPassiveEffects,
} from './ReactFiberWorkLoop.old';
-import {updateContainer, syncUpdates} from './ReactFiberReconciler.old';
+import {updateContainer} from './ReactFiberReconciler.old';
import {emptyContextObject} from './ReactFiberContext.old';
import {Sync} from './ReactFiberExpirationTime.old';
import {
@@ -258,7 +258,7 @@ export const scheduleRoot: ScheduleRoot = (
return;
}
flushPassiveEffects();
- syncUpdates(() => {
+ flushSync(() => {
updateContainer(element, root, null, null);
});
}
diff --git a/packages/react-reconciler/src/ReactFiberReconciler.js b/packages/react-reconciler/src/ReactFiberReconciler.js
index 1215a5f3f4ea3..311a76fc66131 100644
--- a/packages/react-reconciler/src/ReactFiberReconciler.js
+++ b/packages/react-reconciler/src/ReactFiberReconciler.js
@@ -21,7 +21,6 @@ import {
batchedUpdates as batchedUpdates_old,
unbatchedUpdates as unbatchedUpdates_old,
deferredUpdates as deferredUpdates_old,
- syncUpdates as syncUpdates_old,
discreteUpdates as discreteUpdates_old,
flushDiscreteUpdates as flushDiscreteUpdates_old,
flushControlled as flushControlled_old,
@@ -49,7 +48,6 @@ import {
batchedUpdates as batchedUpdates_new,
unbatchedUpdates as unbatchedUpdates_new,
deferredUpdates as deferredUpdates_new,
- syncUpdates as syncUpdates_new,
discreteUpdates as discreteUpdates_new,
flushDiscreteUpdates as flushDiscreteUpdates_new,
flushControlled as flushControlled_new,
@@ -88,9 +86,6 @@ export const unbatchedUpdates = enableNewReconciler
export const deferredUpdates = enableNewReconciler
? deferredUpdates_new
: deferredUpdates_old;
-export const syncUpdates = enableNewReconciler
- ? syncUpdates_new
- : syncUpdates_old;
export const discreteUpdates = enableNewReconciler
? discreteUpdates_new
: discreteUpdates_old;
diff --git a/packages/react-reconciler/src/ReactFiberReconciler.new.js b/packages/react-reconciler/src/ReactFiberReconciler.new.js
index 4b694f7665125..e18bc39b6caee 100644
--- a/packages/react-reconciler/src/ReactFiberReconciler.new.js
+++ b/packages/react-reconciler/src/ReactFiberReconciler.new.js
@@ -56,7 +56,6 @@ import {
flushSync,
flushControlled,
deferredUpdates,
- syncUpdates,
discreteUpdates,
flushDiscreteUpdates,
flushPassiveEffects,
@@ -306,7 +305,6 @@ export {
batchedUpdates,
unbatchedUpdates,
deferredUpdates,
- syncUpdates,
discreteUpdates,
flushDiscreteUpdates,
flushControlled,
diff --git a/packages/react-reconciler/src/ReactFiberReconciler.old.js b/packages/react-reconciler/src/ReactFiberReconciler.old.js
index 38059c6820805..396e2ef8c1085 100644
--- a/packages/react-reconciler/src/ReactFiberReconciler.old.js
+++ b/packages/react-reconciler/src/ReactFiberReconciler.old.js
@@ -56,7 +56,6 @@ import {
flushSync,
flushControlled,
deferredUpdates,
- syncUpdates,
discreteUpdates,
flushDiscreteUpdates,
flushPassiveEffects,
@@ -308,7 +307,6 @@ export {
batchedUpdates,
unbatchedUpdates,
deferredUpdates,
- syncUpdates,
discreteUpdates,
flushDiscreteUpdates,
flushControlled,
diff --git a/packages/react-reconciler/src/ReactFiberWorkLoop.new.js b/packages/react-reconciler/src/ReactFiberWorkLoop.new.js
index 0e9b9caaf08ae..43bb00cc78fc1 100644
--- a/packages/react-reconciler/src/ReactFiberWorkLoop.new.js
+++ b/packages/react-reconciler/src/ReactFiberWorkLoop.new.js
@@ -1008,15 +1008,6 @@ export function deferredUpdates(fn: () => A): A {
return runWithPriority(NormalSchedulerPriority, fn);
}
-export function syncUpdates(
- fn: (A, B, C) => R,
- a: A,
- b: B,
- c: C,
-): R {
- return runWithPriority(ImmediateSchedulerPriority, fn.bind(null, a, b, c));
-}
-
function flushPendingDiscreteUpdates() {
if (rootsWithPendingDiscreteUpdates !== null) {
// For each root with pending discrete updates, schedule a callback to
@@ -1113,7 +1104,11 @@ export function flushSync(fn: A => R, a: A): R {
}
executionContext |= BatchedContext;
try {
- return runWithPriority(ImmediateSchedulerPriority, fn.bind(null, a));
+ if (fn) {
+ return runWithPriority(ImmediateSchedulerPriority, fn.bind(null, a));
+ } else {
+ return (undefined: $FlowFixMe);
+ }
} finally {
executionContext = prevExecutionContext;
// Flush the immediate callbacks that were scheduled during this batch.
diff --git a/packages/react-reconciler/src/ReactFiberWorkLoop.old.js b/packages/react-reconciler/src/ReactFiberWorkLoop.old.js
index daadbbc570fd3..a319602c388f4 100644
--- a/packages/react-reconciler/src/ReactFiberWorkLoop.old.js
+++ b/packages/react-reconciler/src/ReactFiberWorkLoop.old.js
@@ -1065,15 +1065,6 @@ export function deferredUpdates(fn: () => A): A {
return runWithPriority(NormalPriority, fn);
}
-export function syncUpdates(
- fn: (A, B, C) => R,
- a: A,
- b: B,
- c: C,
-): R {
- return runWithPriority(ImmediatePriority, fn.bind(null, a, b, c));
-}
-
function flushPendingDiscreteUpdates() {
if (rootsWithPendingDiscreteUpdates !== null) {
// For each root with pending discrete updates, schedule a callback to
@@ -1167,7 +1158,11 @@ export function flushSync(fn: A => R, a: A): R {
}
executionContext |= BatchedContext;
try {
- return runWithPriority(ImmediatePriority, fn.bind(null, a));
+ if (fn) {
+ return runWithPriority(ImmediatePriority, fn.bind(null, a));
+ } else {
+ return (undefined: $FlowFixMe);
+ }
} finally {
executionContext = prevExecutionContext;
// Flush the immediate callbacks that were scheduled during this batch.
diff --git a/packages/react-reconciler/src/__tests__/ReactHooksWithNoopRenderer-test.js b/packages/react-reconciler/src/__tests__/ReactHooksWithNoopRenderer-test.js
index 13ea6cf0748ee..5dff2fde2c055 100644
--- a/packages/react-reconciler/src/__tests__/ReactHooksWithNoopRenderer-test.js
+++ b/packages/react-reconciler/src/__tests__/ReactHooksWithNoopRenderer-test.js
@@ -1656,7 +1656,7 @@ describe('ReactHooksWithNoopRenderer', () => {
});
});
- it('flushes passive effects when flushing discrete updates', () => {
+ it('does not flush non-discrete passive effects when flushing sync', () => {
let _updateCount;
function Counter(props) {
const [count, updateCount] = useState(0);
@@ -1678,28 +1678,28 @@ describe('ReactHooksWithNoopRenderer', () => {
expect(ReactNoop.getChildren()).toEqual([span('Count: 0')]);
}).toErrorDev(['An update to Counter ran an effect']);
- // A discrete event forces the passive effect to be flushed --
- // updateCount(1) happens first, so 2 wins.
- ReactNoop.flushDiscreteUpdates();
- ReactNoop.discreteUpdates(() => {
- // (use batchedUpdates to silence the act() warning)
- ReactNoop.batchedUpdates(() => {
+ // A flush sync doesn't cause the passive effects to fire.
+ // So we haven't added the other update yet.
+ act(() => {
+ ReactNoop.flushSync(() => {
_updateCount(2);
});
});
- expect(Scheduler).toHaveYielded(['Will set count to 1']);
- expect(() => {
- expect(Scheduler).toFlushAndYield(['Count: 2']);
- }).toErrorDev([
- 'An update to Counter ran an effect',
- 'An update to Counter ran an effect',
+
+ // As a result we, somewhat surprisingly, commit them in the opposite order.
+ // This should be fine because any non-discrete set of work doesn't guarantee order
+ // and easily could've happened slightly later too.
+ expect(Scheduler).toHaveYielded([
+ 'Will set count to 1',
+ 'Count: 2',
+ 'Count: 1',
]);
- expect(ReactNoop.getChildren()).toEqual([span('Count: 2')]);
+ expect(ReactNoop.getChildren()).toEqual([span('Count: 1')]);
});
// @gate enableSchedulerTracing
- it('flushes passive effects when flushing discrete updates (with tracing)', () => {
+ it('does not flush non-discrete passive effects when flushing sync (with tracing)', () => {
const onInteractionScheduledWorkCompleted = jest.fn();
const onWorkCanceled = jest.fn();
SchedulerTracing.unstable_subscribe({
@@ -1744,24 +1744,20 @@ describe('ReactHooksWithNoopRenderer', () => {
expect(onInteractionScheduledWorkCompleted).toHaveBeenCalledTimes(0);
- // A discrete event forces the passive effect to be flushed --
- // updateCount(1) happens first, so 2 wins.
- ReactNoop.flushDiscreteUpdates();
- ReactNoop.discreteUpdates(() => {
- // (use batchedUpdates to silence the act() warning)
- ReactNoop.batchedUpdates(() => {
+ // A flush sync doesn't cause the passive effects to fire.
+ act(() => {
+ ReactNoop.flushSync(() => {
_updateCount(2);
});
});
- expect(Scheduler).toHaveYielded(['Will set count to 1']);
- expect(() => {
- expect(Scheduler).toFlushAndYield(['Count: 2']);
- }).toErrorDev([
- 'An update to Counter ran an effect',
- 'An update to Counter ran an effect',
+
+ expect(Scheduler).toHaveYielded([
+ 'Will set count to 1',
+ 'Count: 2',
+ 'Count: 1',
]);
- expect(ReactNoop.getChildren()).toEqual([span('Count: 2')]);
+ expect(ReactNoop.getChildren()).toEqual([span('Count: 1')]);
expect(onInteractionScheduledWorkCompleted).toHaveBeenCalledTimes(1);
expect(onWorkCanceled).toHaveBeenCalledTimes(0);