Skip to content

Commit 7edcf3f

Browse files
rickhanloniiAndyPengc12
authored andcommitted
Noop unstable_batchedUpdates (facebook#28120)
## Overview `unstable_batchedUpdates` is effectively a no-op outside of legacy mode, this PR makes it an actual no-op outside legacy mode.
1 parent 8e201ad commit 7edcf3f

File tree

6 files changed

+49
-29
lines changed

6 files changed

+49
-29
lines changed

packages/react-dom/index.classic.fb.js

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ export {
2323
findDOMNode,
2424
flushSync,
2525
unmountComponentAtNode,
26-
unstable_batchedUpdates,
2726
unstable_createEventHandle,
2827
unstable_renderSubtreeIntoContainer,
2928
unstable_runWithPriority, // DO NOT USE: Temporarily exposed to migrate off of Scheduler.runWithPriority.
@@ -38,6 +37,11 @@ export {
3837
version,
3938
} from './src/client/ReactDOM';
4039

41-
export {createRoot, hydrateRoot, render} from './src/client/ReactDOMRootFB';
40+
export {
41+
createRoot,
42+
hydrateRoot,
43+
render,
44+
unstable_batchedUpdates,
45+
} from './src/client/ReactDOMRootFB';
4246

4347
export {Internals as __SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED};

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -248,7 +248,7 @@ describe('ReactMount', () => {
248248
expect(calls).toBe(5);
249249
});
250250

251-
// @gate !disableLegacyMode
251+
// @gate !disableLegacyMode && classic
252252
it('initial mount of legacy root is sync inside batchedUpdates, as if it were wrapped in flushSync', () => {
253253
const container1 = document.createElement('div');
254254
const container2 = document.createElement('div');

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

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ describe('ReactLegacyUpdates', () => {
3232
assertLog = InternalTestUtils.assertLog;
3333
});
3434

35-
// @gate !disableLegacyMode
35+
// @gate !disableLegacyMode && classic
3636
it('should batch state when updating state twice', () => {
3737
let updateCount = 0;
3838

@@ -63,7 +63,7 @@ describe('ReactLegacyUpdates', () => {
6363
expect(updateCount).toBe(1);
6464
});
6565

66-
// @gate !disableLegacyMode
66+
// @gate !disableLegacyMode && classic
6767
it('should batch state when updating two different state keys', () => {
6868
let updateCount = 0;
6969

@@ -97,7 +97,7 @@ describe('ReactLegacyUpdates', () => {
9797
expect(updateCount).toBe(1);
9898
});
9999

100-
// @gate !disableLegacyMode
100+
// @gate !disableLegacyMode && classic
101101
it('should batch state and props together', () => {
102102
let updateCount = 0;
103103

@@ -131,7 +131,7 @@ describe('ReactLegacyUpdates', () => {
131131
expect(updateCount).toBe(1);
132132
});
133133

134-
// @gate !disableLegacyMode
134+
// @gate !disableLegacyMode && classic
135135
it('should batch parent/child state updates together', () => {
136136
let parentUpdateCount = 0;
137137

@@ -187,7 +187,7 @@ describe('ReactLegacyUpdates', () => {
187187
expect(childUpdateCount).toBe(1);
188188
});
189189

190-
// @gate !disableLegacyMode
190+
// @gate !disableLegacyMode && classic
191191
it('should batch child/parent state updates together', () => {
192192
let parentUpdateCount = 0;
193193

@@ -245,7 +245,7 @@ describe('ReactLegacyUpdates', () => {
245245
expect(childUpdateCount).toBe(1);
246246
});
247247

248-
// @gate !disableLegacyMode
248+
// @gate !disableLegacyMode && classic
249249
it('should support chained state updates', () => {
250250
let updateCount = 0;
251251

@@ -286,7 +286,7 @@ describe('ReactLegacyUpdates', () => {
286286
expect(updateCount).toBe(2);
287287
});
288288

289-
// @gate !disableLegacyMode
289+
// @gate !disableLegacyMode && classic
290290
it('should batch forceUpdate together', () => {
291291
let shouldUpdateCount = 0;
292292
let updateCount = 0;
@@ -548,7 +548,7 @@ describe('ReactLegacyUpdates', () => {
548548
);
549549
});
550550

551-
// @gate !disableLegacyMode
551+
// @gate !disableLegacyMode && classic
552552
it('should queue mount-ready handlers across different roots', () => {
553553
// We'll define two components A and B, then update both of them. When A's
554554
// componentDidUpdate handlers is called, B's DOM should already have been
@@ -849,7 +849,7 @@ describe('ReactLegacyUpdates', () => {
849849
expect(callbackCount).toBe(1);
850850
});
851851

852-
// @gate !disableLegacyMode
852+
// @gate !disableLegacyMode && classic
853853
it('does not call render after a component as been deleted', () => {
854854
let renderCount = 0;
855855
let componentB = null;

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

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@ import {
3232
import {createEventHandle} from 'react-dom-bindings/src/client/ReactDOMEventHandle';
3333

3434
import {
35-
batchedUpdates,
3635
flushSync as flushSyncWithoutWarningIfAlreadyRendering,
3736
isAlreadyRendering,
3837
injectIntoDevTools,
@@ -167,9 +166,16 @@ function flushSync<R>(fn: (() => R) | void): R | void {
167166
// Expose findDOMNode on internals
168167
Internals.findDOMNode = findDOMNode;
169168

169+
function unstable_batchedUpdates<A, R>(fn: (a: A) => R, a: A): R {
170+
// batchedUpdates was a legacy mode feature that is a no-op outside of
171+
// legacy mode. In 19, we made it an actual no-op, but we're keeping it
172+
// for now since there may be libraries that still include it.
173+
return fn(a);
174+
}
175+
170176
export {
171177
createPortal,
172-
batchedUpdates as unstable_batchedUpdates,
178+
unstable_batchedUpdates,
173179
flushSync,
174180
ReactVersion as version,
175181
// Disabled behind disableLegacyReactDOMAPIs
@@ -196,7 +202,7 @@ Internals.Events = [
196202
getFiberCurrentPropsFromNode,
197203
enqueueStateRestore,
198204
restoreStateIfNeeded,
199-
batchedUpdates,
205+
unstable_batchedUpdates,
200206
];
201207

202208
const foundDevTools = injectIntoDevTools({

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ import {
4242
} from 'react-dom-bindings/src/client/HTMLNodeType';
4343

4444
import {
45+
batchedUpdates,
4546
createContainer,
4647
createHydrationContainer,
4748
findHostInstanceWithNoPortals,
@@ -416,3 +417,5 @@ export function unstable_renderSubtreeIntoContainer(
416417
callback,
417418
);
418419
}
420+
421+
export {batchedUpdates as unstable_batchedUpdates};

packages/react-reconciler/src/ReactFiberWorkLoop.js

Lines changed: 21 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ import {
3939
disableLegacyContext,
4040
alwaysThrottleRetries,
4141
enableInfiniteRenderLoopDetection,
42+
disableLegacyMode,
4243
} from 'shared/ReactFeatureFlags';
4344
import ReactSharedInternals from 'shared/ReactSharedInternals';
4445
import is from 'shared/objectIs';
@@ -1456,21 +1457,27 @@ export function deferredUpdates<A>(fn: () => A): A {
14561457
}
14571458

14581459
export function batchedUpdates<A, R>(fn: A => R, a: A): R {
1459-
const prevExecutionContext = executionContext;
1460-
executionContext |= BatchedContext;
1461-
try {
1460+
if (disableLegacyMode) {
1461+
// batchedUpdates is a no-op now, but there's still some internal react-dom
1462+
// code calling it, that we can't remove until we remove legacy mode.
14621463
return fn(a);
1463-
} finally {
1464-
executionContext = prevExecutionContext;
1465-
// If there were legacy sync updates, flush them at the end of the outer
1466-
// most batchedUpdates-like method.
1467-
if (
1468-
executionContext === NoContext &&
1469-
// Treat `act` as if it's inside `batchedUpdates`, even in legacy mode.
1470-
!(__DEV__ && ReactCurrentActQueue.isBatchingLegacy)
1471-
) {
1472-
resetRenderTimer();
1473-
flushSyncWorkOnLegacyRootsOnly();
1464+
} else {
1465+
const prevExecutionContext = executionContext;
1466+
executionContext |= BatchedContext;
1467+
try {
1468+
return fn(a);
1469+
} finally {
1470+
executionContext = prevExecutionContext;
1471+
// If there were legacy sync updates, flush them at the end of the outer
1472+
// most batchedUpdates-like method.
1473+
if (
1474+
executionContext === NoContext &&
1475+
// Treat `act` as if it's inside `batchedUpdates`, even in legacy mode.
1476+
!(__DEV__ && ReactCurrentActQueue.isBatchingLegacy)
1477+
) {
1478+
resetRenderTimer();
1479+
flushSyncWorkOnLegacyRootsOnly();
1480+
}
14741481
}
14751482
}
14761483
}

0 commit comments

Comments
 (0)