Repository: facebook/react
Pull request: devtools: Display actual ReactDOM API name in root type

First commit for previous, second for new behavior

## Summary

In the devtools side-panel we display what root type a particular element belongs too. However, only for `createRoot` does the current label resemble the actual usage. `createLegacyRoot()` sounds like a function the library user called but it's only an internal name.

For new versions of React, devtools we will now use the same names that are exported from `react-dom`:
`render()`, `hydrate()`, `createRoot()` and `hydrateRoot()`.

## How did you test this change?

- Include `rootType` in the inspected element serializer
- Split PR into commits showcasing previous and new behavior
- [x] CI green

Changed files:
filename: packages/react-devtools-shared/src/__tests__/inspectedElement-test.js
patch: @@ -176,6 +176,7 @@ describe('InspectedElement', () => {
           "a": 1,
           "b": "abc",
         },
+        "rootType": "render()",
         "state": null,
       }
     `);
@@ -1584,6 +1585,7 @@ describe('InspectedElement', () => {
           "a": 1,
           "b": "abc",
         },
+        "rootType": "render()",
         "state": null,
       }
     `);
@@ -1912,6 +1914,7 @@ describe('InspectedElement', () => {
         "id": 2,
         "owners": null,
         "props": Object {},
+        "rootType": "render()",
         "state": null,
       }
     `);
@@ -1944,11 +1947,67 @@ describe('InspectedElement', () => {
         "id": 2,
         "owners": null,
         "props": Object {},
+        "rootType": "render()",
         "state": null,
       }
     `);
   });
 
+  it('should display the root type for ReactDOM.hydrate', async () => {
+    const Example = () => <div />;
+
+    await utils.actAsync(() => {
+      const container = document.createElement('div');
+      container.innerHTML = '<div></div>';
+      withErrorsOrWarningsIgnored(
+        ['ReactDOM.hydrate is no longer supported in React 18'],
+        () => {
+          ReactDOM.hydrate(<Example />, container);
+        },
+      );
+    }, false);
+
+    const inspectedElement = await inspectElementAtIndex(0);
+    expect(inspectedElement.rootType).toMatchInlineSnapshot(`"hydrate()"`);
+  });
+
+  it('should display the root type for ReactDOM.render', async () => {
+    const Example = () => <div />;
+
+    await utils.actAsync(() => {
+      const container = document.createElement('div');
+      legacyRender(<Example />, container);
+    }, false);
+
+    const inspectedElement = await inspectElementAtIndex(0);
+    expect(inspectedElement.rootType).toMatchInlineSnapshot(`"render()"`);
+  });
+
+  it('should display the root type for ReactDOM.hydrateRoot', async () => {
+    const Example = () => <div />;
+
+    await utils.actAsync(() => {
+      const container = document.createElement('div');
+      container.innerHTML = '<div></div>';
+      ReactDOM.hydrateRoot(container).render(<Example />);
+    }, false);
+
+    const inspectedElement = await inspectElementAtIndex(0);
+    expect(inspectedElement.rootType).toMatchInlineSnapshot(`"hydrateRoot()"`);
+  });
+
+  it('should display the root type for ReactDOM.createRoot', async () => {
+    const Example = () => <div />;
+
+    await utils.actAsync(() => {
+      const container = document.createElement('div');
+      ReactDOM.createRoot(container).render(<Example />);
+    }, false);
+
+    const inspectedElement = await inspectElementAtIndex(0);
+    expect(inspectedElement.rootType).toMatchInlineSnapshot(`"createRoot()"`);
+  });
+
   describe('$r', () => {
     it('should support function components', async () => {
       const Example = () => {

filename: packages/react-devtools-shared/src/__tests__/inspectedElementSerializer.js
patch: @@ -30,6 +30,7 @@ export function print(inspectedElement, serialize, indent) {
     id: inspectedElement.id,
     owners: inspectedElement.owners,
     props: inspectedElement.props,
+    rootType: inspectedElement.rootType,
     state: inspectedElement.state,
   });
 }

filename: packages/react-devtools-shared/src/__tests__/legacy/inspectElement-test.js
patch: @@ -83,6 +83,7 @@ describe('InspectedElementContext', () => {
           "a": 1,
           "b": "abc",
         },
+        "rootType": null,
         "state": null,
       }
     `);
@@ -133,6 +134,7 @@ describe('InspectedElementContext', () => {
           "value_null": null,
           "value_undefined": undefined,
         },
+        "rootType": null,
         "state": null,
       }
     `);
@@ -408,6 +410,7 @@ describe('InspectedElementContext', () => {
             "preview_long": Generator,
           },
         },
+        "rootType": null,
         "state": null,
       }
     `);
@@ -461,6 +464,7 @@ describe('InspectedElementContext', () => {
             "number": 42,
           },
         },
+        "rootType": null,
         "state": null,
       }
     `);
@@ -552,6 +556,7 @@ describe('InspectedElementContext', () => {
             "enumerableStringBase": 1,
           },
         },
+        "rootType": null,
         "state": null,
       }
     `);

filename: packages/react-reconciler/src/ReactFiberRoot.new.js
patch: @@ -83,10 +83,10 @@ function FiberRootNode(containerInfo, tag, hydrate) {
   if (__DEV__) {
     switch (tag) {
       case ConcurrentRoot:
-        this._debugRootType = 'createRoot()';
+        this._debugRootType = hydrate ? 'hydrateRoot()' : 'createRoot()';
         break;
       case LegacyRoot:
-        this._debugRootType = 'createLegacyRoot()';
+        this._debugRootType = hydrate ? 'hydrate()' : 'render()';
         break;
     }
   }

filename: packages/react-reconciler/src/ReactFiberRoot.old.js
patch: @@ -83,10 +83,10 @@ function FiberRootNode(containerInfo, tag, hydrate) {
   if (__DEV__) {
     switch (tag) {
       case ConcurrentRoot:
-        this._debugRootType = 'createRoot()';
+        this._debugRootType = hydrate ? 'hydrateRoot()' : 'createRoot()';
         break;
       case LegacyRoot:
-        this._debugRootType = 'createLegacyRoot()';
+        this._debugRootType = hydrate ? 'hydrate()' : 'render()';
         break;
     }
   }