Repository: facebook/react
Pull request: devtools: Remove ForwardRef/Memo from display name if `displayName` is set

## Summary

The displayed name of e.g. 
```jsx
const Component = forwardRef(function Component() {
  return null;
});
Component.displayName = `Component`;
```
will no longer include the `ForwardRef` badge in the element tree. This also applies to `React.memo`.

This matches how display names are computed in [`getComponentNameFromType`](https://github.com/facebook/react/blob/c76e4dbbc1f18f8ba2c8f02d34cae9ad0954a7f0/packages/shared/getComponentNameFromType.js#L92)  e.g. in warnings.


Closes https://github.com/facebook/react/issues/21939
## Test Plan

- [x] CI green
- [x] ~linked codesandboxes produce desired display name~ See `ForwardRefComponentWithCustomDisplayName` in `react-devtools-shell`
   Before:
   ![devtools-memo-custom-name-before](https://user-images.githubusercontent.com/12292047/176991670-2aff0f72-ca31-4f14-a51f-0c1ed3dd573d.png)
   After:
   ![devtools-memo-custom-name-after](https://user-images.githubusercontent.com/12292047/176991686-a329cb62-7d7e-48f1-9362-94e9faefd154.png)
   ```diff
   -Custom ForwardRef
   +Custom 
   ```

Changed files:
filename: packages/react-devtools-shared/src/__tests__/profilingCharts-test.js
patch: @@ -125,8 +125,8 @@ describe('profiling charts', () => {
               "actualDuration": 0,
               "didRender": true,
               "id": 5,
-              "label": "Child key=\\"third\\" (<0.1ms of <0.1ms)",
-              "name": "Child",
+              "label": "Memo(Child) key=\\"third\\" (<0.1ms of <0.1ms)",
+              "name": "Memo(Child)",
               "offset": 15,
               "selfDuration": 0,
               "treeBaseDuration": 0,
@@ -135,8 +135,8 @@ describe('profiling charts', () => {
               "actualDuration": 2,
               "didRender": true,
               "id": 4,
-              "label": "Child key=\\"second\\" (2ms of 2ms)",
-              "name": "Child",
+              "label": "Memo(Child) key=\\"second\\" (2ms of 2ms)",
+              "name": "Memo(Child)",
               "offset": 13,
               "selfDuration": 2,
               "treeBaseDuration": 2,
@@ -145,8 +145,8 @@ describe('profiling charts', () => {
               "actualDuration": 3,
               "didRender": true,
               "id": 3,
-              "label": "Child key=\\"first\\" (3ms of 3ms)",
-              "name": "Child",
+              "label": "Memo(Child) key=\\"first\\" (3ms of 3ms)",
+              "name": "Memo(Child)",
               "offset": 10,
               "selfDuration": 3,
               "treeBaseDuration": 3,
@@ -176,8 +176,8 @@ describe('profiling charts', () => {
               "actualDuration": 0,
               "didRender": false,
               "id": 5,
-              "label": "Child key=\\"third\\"",
-              "name": "Child",
+              "label": "Memo(Child) key=\\"third\\"",
+              "name": "Memo(Child)",
               "offset": 15,
               "selfDuration": 0,
               "treeBaseDuration": 0,
@@ -186,8 +186,8 @@ describe('profiling charts', () => {
               "actualDuration": 0,
               "didRender": false,
               "id": 4,
-              "label": "Child key=\\"second\\"",
-              "name": "Child",
+              "label": "Memo(Child) key=\\"second\\"",
+              "name": "Memo(Child)",
               "offset": 13,
               "selfDuration": 0,
               "treeBaseDuration": 2,
@@ -196,8 +196,8 @@ describe('profiling charts', () => {
               "actualDuration": 0,
               "didRender": false,
               "id": 3,
-              "label": "Child key=\\"first\\"",
-              "name": "Child",
+              "label": "Memo(Child) key=\\"first\\"",
+              "name": "Memo(Child)",
               "offset": 10,
               "selfDuration": 0,
               "treeBaseDuration": 3,
@@ -267,20 +267,20 @@ describe('profiling charts', () => {
           },
           Object {
             "id": 3,
-            "label": "Child (Memo) key=\\"first\\" (3ms)",
-            "name": "Child",
+            "label": "Memo(Child) (Memo) key=\\"first\\" (3ms)",
+            "name": "Memo(Child)",
             "value": 3,
           },
           Object {
             "id": 4,
-            "label": "Child (Memo) key=\\"second\\" (2ms)",
-            "name": "Child",
+            "label": "Memo(Child) (Memo) key=\\"second\\" (2ms)",
+            "name": "Memo(Child)",
             "value": 2,
           },
           Object {
             "id": 5,
-            "label": "Child (Memo) key=\\"third\\" (<0.1ms)",
-            "name": "Child",
+            "label": "Memo(Child) (Memo) key=\\"third\\" (<0.1ms)",
+            "name": "Memo(Child)",
             "value": 0,
           },
         ]

filename: packages/react-devtools-shared/src/__tests__/store-test.js
patch: @@ -1507,16 +1507,16 @@ describe('Store', () => {
             <MyComponent> [ForwardRef]
           ▾ <Anonymous> [ForwardRef]
               <MyComponent2>
-            <Custom> [ForwardRef]
+            <Custom>
             <MyComponent4> [Memo]
           ▾ <MyComponent> [Memo]
               <MyComponent> [ForwardRef]
             <Baz> [withFoo][withBar]
             <Baz> [Memo][withFoo][withBar]
             <Baz> [ForwardRef][withFoo][withBar]
             <Cache>
-            <memoRefOverride> [Memo]
-            <forwardRefOverride> [ForwardRef]
+            <memoRefOverride>
+            <forwardRefOverride>
     `);
   });
 

filename: packages/react-devtools-shared/src/backend/renderer.js
patch: @@ -30,6 +30,7 @@ import {
 import {
   deletePathInObject,
   getDisplayName,
+  getWrappedDisplayName,
   getDefaultComponentFilters,
   getInObject,
   getUID,
@@ -451,10 +452,11 @@ export function getInternalReactConstants(
       case IndeterminateComponent:
         return getDisplayName(resolvedType);
       case ForwardRef:
-        // Mirror https://github.com/facebook/react/blob/7c21bf72ace77094fd1910cc350a548287ef8350/packages/shared/getComponentName.js#L27-L37
-        return (
-          (type && type.displayName) ||
-          getDisplayName(resolvedType, 'Anonymous')
+        return getWrappedDisplayName(
+          elementType,
+          resolvedType,
+          'ForwardRef',
+          'Anonymous',
         );
       case HostRoot:
         const fiberRoot = fiber.stateNode;
@@ -475,10 +477,12 @@ export function getInternalReactConstants(
         return 'Lazy';
       case MemoComponent:
       case SimpleMemoComponent:
-        return (
-          (elementType && elementType.displayName) ||
-          (type && type.displayName) ||
-          getDisplayName(resolvedType, 'Anonymous')
+        // Display name in React does not use `Memo` as a wrapper but fallback name.
+        return getWrappedDisplayName(
+          elementType,
+          resolvedType,
+          'Memo',
+          'Anonymous',
         );
       case SuspenseComponent:
         return 'Suspense';

filename: packages/react-devtools-shared/src/utils.js
patch: @@ -101,6 +101,19 @@ export function getAllEnumerableKeys(
   return keys;
 }
 
+// Mirror https://github.com/facebook/react/blob/7c21bf72ace77094fd1910cc350a548287ef8350/packages/shared/getComponentName.js#L27-L37
+export function getWrappedDisplayName(
+  outerType: mixed,
+  innerType: any,
+  wrapperName: string,
+  fallbackName?: string,
+): string {
+  return (
+    (outerType: any).displayName ||
+    `${wrapperName}(${getDisplayName(innerType, fallbackName)})`
+  );
+}
+
 export function getDisplayName(
   type: Function,
   fallbackName: string = 'Anonymous',
@@ -445,20 +458,6 @@ export function separateDisplayNameAndHOCs(
       break;
   }
 
-  if (type === ElementTypeMemo) {
-    if (hocDisplayNames === null) {
-      hocDisplayNames = ['Memo'];
-    } else {
-      hocDisplayNames.unshift('Memo');
-    }
-  } else if (type === ElementTypeForwardRef) {
-    if (hocDisplayNames === null) {
-      hocDisplayNames = ['ForwardRef'];
-    } else {
-      hocDisplayNames.unshift('ForwardRef');
-    }
-  }
-
   return [displayName, hocDisplayNames];
 }