diff --git a/packages/react-dom/index.classic.fb.js b/packages/react-dom/index.classic.fb.js index e946df7b76db..1264badae76c 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 b771d0105b8e..40676689ee28 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 bcb213ad4ee3..258e12303ec1 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 ee294218ced4..741d24f73181 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 2a31c5f37f21..614aaffc1b7c 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 21819bf9edbc..0fe04f2cc9db 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 4e2951b7d4a5..6796db951106 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 1215a5f3f4ea..311a76fc6613 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 4b694f766512..e18bc39b6cae 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 38059c682080..396e2ef8c108 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 0e9b9caaf08a..43bb00cc78fc 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 daadbbc570fd..a319602c388f 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 13ea6cf0748e..5dff2fde2c05 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);