diff --git a/packages/react-reconciler/src/ReactDebugFiberPerf.js b/packages/react-reconciler/src/ReactDebugFiberPerf.js
index 1c84527e9ce77..0bd2dfb0ad4f9 100644
--- a/packages/react-reconciler/src/ReactDebugFiberPerf.js
+++ b/packages/react-reconciler/src/ReactDebugFiberPerf.js
@@ -21,6 +21,7 @@ import {
Fragment,
ContextProvider,
ContextConsumer,
+ Mode,
} from 'shared/ReactTypeOfWork';
type MeasurementPhase =
@@ -175,6 +176,7 @@ const shouldIgnoreFiber = (fiber: Fiber): boolean => {
case Fragment:
case ContextProvider:
case ContextConsumer:
+ case Mode:
return true;
default:
return false;
diff --git a/packages/react-reconciler/src/__tests__/ReactIncrementalPerf-test.internal.js b/packages/react-reconciler/src/__tests__/ReactIncrementalPerf-test.internal.js
index 854a85efadc8c..d5dc2b6f6ab76 100644
--- a/packages/react-reconciler/src/__tests__/ReactIncrementalPerf-test.internal.js
+++ b/packages/react-reconciler/src/__tests__/ReactIncrementalPerf-test.internal.js
@@ -161,6 +161,64 @@ describe('ReactDebugFiberPerf', () => {
expect(getFlameChart()).toMatchSnapshot();
});
+ it('properly displays the forwardRef component in measurements', () => {
+ const AnonymousForwardRef = React.forwardRef((props, ref) => (
+
+ ));
+ const NamedForwardRef = React.forwardRef(function refForwarder(props, ref) {
+ return ;
+ });
+ function notImportant(props, ref) {
+ return ;
+ }
+ notImportant.displayName = 'OverriddenName';
+ const DisplayNamedForwardRef = React.forwardRef(notImportant);
+
+ ReactNoop.render(
+
+
+
+
+ ,
+ );
+ addComment('Mount');
+ ReactNoop.flush();
+
+ expect(getFlameChart()).toMatchSnapshot();
+ });
+
+ it('does not include StrictMode or AsyncMode components in measurements', () => {
+ ReactNoop.render(
+
+
+
+
+
+
+ ,
+ );
+ addComment('Mount');
+ ReactNoop.flush();
+
+ expect(getFlameChart()).toMatchSnapshot();
+ });
+
+ it('does not include context provider or consumer in measurements', () => {
+ const {Consumer, Provider} = React.createContext(true);
+
+ ReactNoop.render(
+
+
+ {value => }
+
+ ,
+ );
+ addComment('Mount');
+ ReactNoop.flush();
+
+ expect(getFlameChart()).toMatchSnapshot();
+ });
+
it('skips parents during setState', () => {
class A extends React.Component {
render() {
diff --git a/packages/react-reconciler/src/__tests__/__snapshots__/ReactIncrementalPerf-test.internal.js.snap b/packages/react-reconciler/src/__tests__/__snapshots__/ReactIncrementalPerf-test.internal.js.snap
index 48d0e6f4f67cd..40e37fe439489 100644
--- a/packages/react-reconciler/src/__tests__/__snapshots__/ReactIncrementalPerf-test.internal.js.snap
+++ b/packages/react-reconciler/src/__tests__/__snapshots__/ReactIncrementalPerf-test.internal.js.snap
@@ -91,6 +91,36 @@ exports[`ReactDebugFiberPerf deduplicates lifecycle names during commit to reduc
"
`;
+exports[`ReactDebugFiberPerf does not include StrictMode or AsyncMode components in measurements 1`] = `
+"⚛ (Waiting for async callback... will force flush in 5230 ms)
+
+// Mount
+⚛ (React Tree Reconciliation: Completed Root)
+ ⚛ Parent [mount]
+ ⚛ Child [mount]
+
+⚛ (Committing Changes)
+ ⚛ (Committing Snapshot Effects: 0 Total)
+ ⚛ (Committing Host Effects: 1 Total)
+ ⚛ (Calling Lifecycle Methods: 0 Total)
+"
+`;
+
+exports[`ReactDebugFiberPerf does not include context provider or consumer in measurements 1`] = `
+"⚛ (Waiting for async callback... will force flush in 5230 ms)
+
+// Mount
+⚛ (React Tree Reconciliation: Completed Root)
+ ⚛ Parent [mount]
+ ⚛ Child [mount]
+
+⚛ (Committing Changes)
+ ⚛ (Committing Snapshot Effects: 0 Total)
+ ⚛ (Committing Host Effects: 1 Total)
+ ⚛ (Calling Lifecycle Methods: 0 Total)
+"
+`;
+
exports[`ReactDebugFiberPerf does not schedule an extra callback if setState is called during a synchronous commit phase 1`] = `
"⚛ (React Tree Reconciliation: Completed Root)
⚛ Component [mount]
@@ -231,6 +261,26 @@ exports[`ReactDebugFiberPerf measures deprioritized work 1`] = `
"
`;
+exports[`ReactDebugFiberPerf properly displays the forwardRef component in measurements 1`] = `
+"⚛ (Waiting for async callback... will force flush in 5230 ms)
+
+// Mount
+⚛ (React Tree Reconciliation: Completed Root)
+ ⚛ Parent [mount]
+ ⚛ ForwardRef [mount]
+ ⚛ Child [mount]
+ ⚛ ForwardRef(refForwarder) [mount]
+ ⚛ Child [mount]
+ ⚛ ForwardRef(OverriddenName) [mount]
+ ⚛ Child [mount]
+
+⚛ (Committing Changes)
+ ⚛ (Committing Snapshot Effects: 0 Total)
+ ⚛ (Committing Host Effects: 1 Total)
+ ⚛ (Calling Lifecycle Methods: 0 Total)
+"
+`;
+
exports[`ReactDebugFiberPerf recovers from caught errors 1`] = `
"⚛ (Waiting for async callback... will force flush in 5230 ms)
diff --git a/packages/shared/getComponentName.js b/packages/shared/getComponentName.js
index e00bd89725162..23e10d1a73a97 100644
--- a/packages/shared/getComponentName.js
+++ b/packages/shared/getComponentName.js
@@ -14,6 +14,7 @@ import {
REACT_FRAGMENT_TYPE,
REACT_RETURN_TYPE,
REACT_PORTAL_TYPE,
+ REACT_FORWARD_REF_TYPE,
} from 'shared/ReactSymbols';
function getComponentName(fiber: Fiber): string | null {
@@ -34,6 +35,15 @@ function getComponentName(fiber: Fiber): string | null {
case REACT_RETURN_TYPE:
return 'ReactReturn';
}
+ if (typeof type === 'object' && type !== null) {
+ switch (type.$$typeof) {
+ case REACT_FORWARD_REF_TYPE:
+ const functionName = type.render.displayName || type.render.name || '';
+ return functionName !== ''
+ ? `ForwardRef(${functionName})`
+ : 'ForwardRef';
+ }
+ }
return null;
}