Use a shared noop function from shared/noop (#33154)
Stacked on #33150. We use `noop` functions in a lot of places as place holders. I don't think there's any real optimizations we get from having separate instances. This moves them to use a common instance in `shared/noop`.
Sebastian Markbåge committed
May 8, 2025 at 21:33 UTC
21fdf308a1a01af69c28c00a70086aa1bd4c2411
15 files changed
+48
-45
packages/react-dom-bindings/src/client/ReactDOMComponent.js
+2
-2
@@ -63,6 +63,8 @@ import {validateProperties as validateInputProperties} from '../shared/ReactDOMN
63
import {validateProperties as validateUnknownProperties} from '../shared/ReactDOMUnknownPropertyHook';
64
import sanitizeURL from '../shared/sanitizeURL';
65
66
+import noop from 'shared/noop';
67
+
68
import {trackHostMutation} from 'react-reconciler/src/ReactFiberMutationTracking';
69
70
import {
@@ -319,8 +321,6 @@ function checkForUnmatchedText(
321
return false;
322
}
323
322
-function noop() {}
323
-
324
export function trapClickOnNonInteractiveElement(node: HTMLElement) {
325
// Mobile Safari does not fire properly bubble click events on
326
// non-interactive elements, which means delegated click listeners do not
packages/react-dom-bindings/src/client/ReactFiberConfigDOM.js
+7
-6
@@ -139,6 +139,9 @@ import {requestFormReset as requestFormResetOnFiber} from 'react-reconciler/src/
139
import ReactDOMSharedInternals from 'shared/ReactDOMSharedInternals';
140
141
export {default as rendererVersion} from 'shared/ReactVersion';
142
+
143
+import noop from 'shared/noop';
144
+
145
export const rendererPackageName = 'react-dom';
146
export const extraDevToolsConfig = null;
147
@@ -5628,16 +5631,14 @@ type SuspendedState = {
5631
};
5632
let suspendedState: null | SuspendedState = null;
5633
5631
-// We use a noop function when we begin suspending because if possible we want the
5632
-// waitfor step to finish synchronously. If it doesn't we'll return a function to
5633
-// provide the actual unsuspend function and that will get completed when the count
5634
-// hits zero or it will get cancelled if the root starts new work.
5635
-function noop() {}
5636
-
5634
export function startSuspendingCommit(): void {
5635
suspendedState = {
5636
stylesheets: null,
5637
count: 0,
5638
+ // We use a noop function when we begin suspending because if possible we want the
5639
+ // waitfor step to finish synchronously. If it doesn't we'll return a function to
5640
+ // provide the actual unsuspend function and that will get completed when the count
5641
+ // hits zero or it will get cancelled if the root starts new work.
5642
unsuspend: noop,
5643
};
5644
}
packages/react-dom/src/ReactDOMSharedInternals.js
+2
-2
@@ -10,6 +10,8 @@
10
import type {EventPriority} from 'react-reconciler/src/ReactEventPriorities';
11
import type {HostDispatcher} from './shared/ReactDOMTypes';
12
13
+import noop from 'shared/noop';
14
+
15
// This should line up with NoEventPriority from react-reconciler/src/ReactEventPriorities
16
// but we can't depend on the react-reconciler from this isomorphic code.
17
export const NoEventPriority: EventPriority = (0: any);
@@ -24,8 +26,6 @@ type ReactDOMInternals = {
26
) => null | Element | Text),
27
};
28
27
-function noop() {}
28
-
29
function requestFormReset(element: HTMLFormElement) {
30
throw new Error(
31
'Invalid form element. requestFormReset must be passed a form that was ' +
packages/react-dom/src/ReactDOMSharedInternalsFB.js
+2
-2
@@ -12,6 +12,8 @@ import type {HostDispatcher} from './shared/ReactDOMTypes';
12
13
import {NoEventPriority} from 'react-reconciler/src/ReactEventPriorities';
14
15
+import noop from 'shared/noop';
16
+
17
type ReactDOMInternals = {
18
Events: [any, any, any, any, any, any],
19
d /* ReactDOMCurrentDispatcher */: HostDispatcher,
@@ -23,8 +25,6 @@ type ReactDOMInternals = {
25
) => null | Element | Text),
26
};
27
26
-function noop() {}
27
-
28
const DefaultDispatcher: HostDispatcher = {
29
f /* flushSyncWork */: noop,
30
r /* requestFormReset */: noop,
packages/react-dom/src/client/ReactDOMRootFB.js
+6
-8
@@ -70,6 +70,8 @@ import {
70
71
import assign from 'shared/assign';
72
73
+import noop from 'shared/noop';
74
+
75
// Provided by www
76
const ReactFiberErrorDialogWWW = require('ReactFiberErrorDialog');
77
@@ -206,14 +208,10 @@ function getReactRootElementInContainer(container: any) {
208
}
209
}
210
209
-function noopOnRecoverableError() {
210
- // This isn't reachable because onRecoverableError isn't called in the
211
- // legacy API.
212
-}
213
-
214
-function noopOnDefaultTransitionIndicator() {
215
- // Noop
216
-}
211
+// This isn't reachable because onRecoverableError isn't called in the
212
+// legacy API.
213
+const noopOnRecoverableError = noop;
214
+const noopOnDefaultTransitionIndicator = noop;
215
216
function legacyCreateRootFromDOMContainer(
217
container: Container,
packages/react-reconciler/src/ReactFiberThenable.js
+2
-2
@@ -18,6 +18,8 @@ import {getWorkInProgressRoot} from './ReactFiberWorkLoop';
18
19
import ReactSharedInternals from 'shared/ReactSharedInternals';
20
21
+import noop from 'shared/noop';
22
+
23
opaque type ThenableStateDev = {
24
didWarnAboutUncachedPromise: boolean,
25
thenables: Array<Thenable<any>>,
@@ -95,8 +97,6 @@ export function isThenableResolved(thenable: Thenable<mixed>): boolean {
97
return status === 'fulfilled' || status === 'rejected';
98
}
99
98
-function noop(): void {}
99
-
100
export function trackUsedThenable<T>(
101
thenableState: ThenableState,
102
thenable: Thenable<T>,
packages/react-server/src/ReactFizzHooks.js
+2
-2
@@ -47,6 +47,8 @@ import {
47
import {checkAttributeStringCoercion} from 'shared/CheckStringCoercion';
48
import {getFormState} from './ReactFizzServer';
49
50
+import noop from 'shared/noop';
51
+
52
type BasicStateAction<S> = (S => S) | S;
53
type Dispatch<A> = A => void;
54
@@ -795,8 +797,6 @@ function useMemoCache(size: number): Array<mixed> {
797
return data;
798
}
799
798
-function noop(): void {}
799
-
800
function clientHookNotSupported() {
801
throw new Error(
802
'Cannot use state or effect Hooks in renderToHTML because ' +
packages/react-server/src/ReactFizzServer.js
+1
-2
@@ -176,6 +176,7 @@ import {
176
} from 'shared/ReactFeatureFlags';
177
178
import assign from 'shared/assign';
179
+import noop from 'shared/noop';
180
import getComponentNameFromType from 'shared/getComponentNameFromType';
181
import isArray from 'shared/isArray';
182
import {SuspenseException, getSuspendedThenable} from './ReactFizzThenable';
@@ -425,8 +426,6 @@ function defaultErrorHandler(error: mixed) {
426
return null;
427
}
428
428
-function noop(): void {}
429
-
429
function RequestInstance(
430
this: $FlowFixMe,
431
resumableState: ResumableState,
packages/react-server/src/ReactFizzThenable.js
+2
-2
@@ -20,6 +20,8 @@ import type {
20
RejectedThenable,
21
} from 'shared/ReactTypes';
22
23
+import noop from 'shared/noop';
24
+
25
export opaque type ThenableState = Array<Thenable<any>>;
26
27
// An error that is thrown (e.g. by `use`) to trigger Suspense. If we
@@ -40,8 +42,6 @@ export function createThenableState(): ThenableState {
42
return [];
43
}
44
43
-function noop(): void {}
44
-
45
export function trackUsedThenable<T>(
46
thenableState: ThenableState,
47
thenable: Thenable<T>,
packages/react-server/src/ReactFlightServer.js
+3
-5
@@ -105,6 +105,8 @@ import {resolveOwner, setCurrentOwner} from './flight/ReactFlightCurrentOwner';
105
import {getOwnerStackByComponentInfoInDev} from 'shared/ReactComponentInfoStack';
106
import {resetOwnerStackLimit} from 'shared/ReactOwnerStackReset';
107
108
+import noop from 'shared/noop';
109
+
110
import {
111
callComponentInDEV,
112
callLazyInitInDEV,
@@ -443,9 +445,7 @@ function defaultErrorHandler(error: mixed) {
445
// Don't transform to our wrapper
446
}
447
446
-function defaultPostponeHandler(reason: string) {
447
- // Noop
448
-}
448
+const defaultPostponeHandler: (reason: string) => void = noop;
449
450
function RequestInstance(
451
this: $FlowFixMe,
@@ -558,8 +558,6 @@ function RequestInstance(
558
pingedTasks.push(rootTask);
559
}
560
561
-function noop() {}
562
-
561
export function createRequest(
562
model: ReactClientValue,
563
bundlerConfig: ClientManifest,
packages/react-server/src/ReactFlightThenable.js
+2
-2
@@ -20,6 +20,8 @@ import type {
20
RejectedThenable,
21
} from 'shared/ReactTypes';
22
23
+import noop from 'shared/noop';
24
+
25
export opaque type ThenableState = Array<Thenable<any>>;
26
27
// An error that is thrown (e.g. by `use`) to trigger Suspense. If we
@@ -40,8 +42,6 @@ export function createThenableState(): ThenableState {
42
return [];
43
}
44
43
-function noop(): void {}
44
-
45
export function trackUsedThenable<T>(
46
thenableState: ThenableState,
47
thenable: Thenable<T>,
packages/react-test-renderer/src/ReactTestRenderer.js
+3
-3
@@ -60,9 +60,9 @@ import {
60
disableLegacyMode,
61
} from 'shared/ReactFeatureFlags';
62
63
-function defaultOnDefaultTransitionIndicator(): void | (() => void) {
64
- // Noop
65
-}
63
+import noop from 'shared/noop';
64
+
65
+const defaultOnDefaultTransitionIndicator: () => void | (() => void) = noop;
66
67
// $FlowFixMe[prop-missing]: This is only in the development export.
68
const act = React.act;
packages/react/src/ReactChildren.js
+1
-2
@@ -16,6 +16,7 @@ import type {
16
} from 'shared/ReactTypes';
17
18
import isArray from 'shared/isArray';
19
+import noop from 'shared/noop';
20
import {
21
getIteratorFn,
22
REACT_ELEMENT_TYPE,
@@ -82,8 +83,6 @@ function getElementKey(element: any, index: number): string {
83
return index.toString(36);
84
}
85
85
-function noop() {}
86
-
86
function resolveThenable<T>(thenable: Thenable<T>): T {
87
switch (thenable.status) {
88
case 'fulfilled': {
packages/react/src/ReactStartTransition.js
+3
-5
@@ -25,6 +25,8 @@ import {
25
26
import reportGlobalError from 'shared/reportGlobalError';
27
28
+import noop from 'shared/noop';
29
+
30
export type Transition = {
31
types: null | TransitionTypes, // enableViewTransition
32
gesture: null | GestureProvider, // enableGestureTransition
@@ -177,9 +179,7 @@ export function startGestureTransition(
179
} finally {
180
ReactSharedInternals.T = prevTransition;
181
}
180
- return function cancelGesture() {
181
- // Noop
182
- };
182
+ return noop;
183
}
184
185
function warnAboutTransitionSubscriptions(
@@ -200,5 +200,3 @@ function warnAboutTransitionSubscriptions(
200
}
201
}
202
}
203
-
204
-function noop() {}
packages/shared/noop.js
new
+10
@@ -0,0 +1,10 @@
1
+/**
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ * @flow
8
+ */
9
+
10
+export default function noop() {}