Skip to content

Commit

Permalink
[DevTools] add support for HostSingleton & HostResource (#25616)
Browse files Browse the repository at this point in the history
## Summary

This is to support two new reconciler work tags `HostSingleton` and
`HostResource` introduced in PRs #25243 #25426. The behavior is
described below.
I also renamed an option in components settings from an internal concept
"host" to more understood "dom nodes"

## How did you test this change?

Tested on the latest Vercel playground app
https://github.com/vercel/app-playground/

Before the change, devtools cannot show correct display name for these
new elements. Also, some unnecessary internal details are exposed to
users.
<img width="1395" alt="image"
src="https://user-images.githubusercontent.com/1001890/199578181-c4e4ea74-baa1-4507-83d0-91a62ad7de5f.png">

After the change, the display names are correctly shown and the "state"
would always be hidden in the detail view.
<img width="1417" alt="image"
src="https://user-images.githubusercontent.com/1001890/199578442-adc1951d-7d5b-4b84-ad64-85bcf7a8ebcc.png">

These elements will also be hidden just like other native dom elements
(e.g. `<div>`)
<img width="836" alt="image"
src="https://user-images.githubusercontent.com/1001890/199578598-2dfacf64-ddc9-42b5-a246-dd0b09f629af.png">
  • Loading branch information
mondaychen committed Nov 7, 2022
1 parent 4bd245e commit 18dff79
Show file tree
Hide file tree
Showing 4 changed files with 64 additions and 40 deletions.
18 changes: 18 additions & 0 deletions packages/react-devtools-shared/src/backend/renderer.js
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,8 @@ export function getInternalReactConstants(
HostComponent: 5,
HostPortal: 4,
HostRoot: 3,
HostResource: 26, // In reality, 18.2+. But doesn't hurt to include it here
HostSingleton: 27, // Same as above
HostText: 6,
IncompleteClassComponent: 17,
IndeterminateComponent: 2,
Expand Down Expand Up @@ -269,6 +271,8 @@ export function getInternalReactConstants(
HostComponent: 5,
HostPortal: 4,
HostRoot: 3,
HostResource: -1, // Doesn't exist yet
HostSingleton: -1, // Doesn't exist yet
HostText: 6,
IncompleteClassComponent: 17,
IndeterminateComponent: 2,
Expand Down Expand Up @@ -300,6 +304,8 @@ export function getInternalReactConstants(
HostComponent: 5,
HostPortal: 4,
HostRoot: 3,
HostResource: -1, // Doesn't exist yet
HostSingleton: -1, // Doesn't exist yet
HostText: 6,
IncompleteClassComponent: 17,
IndeterminateComponent: 2,
Expand Down Expand Up @@ -331,6 +337,8 @@ export function getInternalReactConstants(
HostComponent: 7,
HostPortal: 6,
HostRoot: 5,
HostResource: -1, // Doesn't exist yet
HostSingleton: -1, // Doesn't exist yet
HostText: 8,
IncompleteClassComponent: -1, // Doesn't exist yet
IndeterminateComponent: 4,
Expand Down Expand Up @@ -362,6 +370,8 @@ export function getInternalReactConstants(
HostComponent: 5,
HostPortal: 4,
HostRoot: 3,
HostResource: -1, // Doesn't exist yet
HostSingleton: -1, // Doesn't exist yet
HostText: 6,
IncompleteClassComponent: -1, // Doesn't exist yet
IndeterminateComponent: 0,
Expand Down Expand Up @@ -401,6 +411,8 @@ export function getInternalReactConstants(
IndeterminateComponent,
ForwardRef,
HostRoot,
HostResource,
HostSingleton,
HostComponent,
HostPortal,
HostText,
Expand Down Expand Up @@ -466,6 +478,8 @@ export function getInternalReactConstants(
}
return null;
case HostComponent:
case HostSingleton:
case HostResource:
return type;
case HostPortal:
case HostText:
Expand Down Expand Up @@ -600,6 +614,8 @@ export function attach(
Fragment,
FunctionComponent,
HostRoot,
HostResource,
HostSingleton,
HostPortal,
HostComponent,
HostText,
Expand Down Expand Up @@ -1044,6 +1060,8 @@ export function attach(
case HostRoot:
return ElementTypeRoot;
case HostComponent:
case HostResource:
case HostSingleton:
return ElementTypeHostComponent;
case HostPortal:
case HostText:
Expand Down
2 changes: 2 additions & 0 deletions packages/react-devtools-shared/src/backend/types.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ export type WorkTagMap = {
HostComponent: WorkTag,
HostPortal: WorkTag,
HostRoot: WorkTag,
HostResource: WorkTag,
HostSingleton: WorkTag,
HostText: WorkTag,
IncompleteClassComponent: WorkTag,
IndeterminateComponent: WorkTag,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

import {copy} from 'clipboard-js';
import * as React from 'react';
import {ElementTypeHostComponent} from 'react-devtools-shared/src/types';
import Button from '../Button';
import ButtonIcon from '../ButtonIcon';
import KeyValue from './KeyValue';
Expand All @@ -33,52 +34,55 @@ export default function InspectedElementStateTree({
inspectedElement,
store,
}: Props): React.Node {
const {state} = inspectedElement;
const {state, type} = inspectedElement;

// HostSingleton and HostResource may have state that we don't want to expose to users
const isHostComponent = type === ElementTypeHostComponent;

const entries = state != null ? Object.entries(state) : null;
const isEmpty = entries === null || entries.length === 0;

if (isEmpty || isHostComponent) {
return null;
}

if (entries !== null) {
entries.sort(alphaSortEntries);
}

const isEmpty = entries === null || entries.length === 0;

const handleCopy = () => copy(serializeDataForCopy(((state: any): Object)));

if (isEmpty) {
return null;
} else {
return (
<div className={styles.InspectedElementTree}>
<div className={styles.HeaderRow}>
<div className={styles.Header}>state</div>
{!isEmpty && (
<Button onClick={handleCopy} title="Copy to clipboard">
<ButtonIcon type="copy" />
</Button>
)}
</div>
{isEmpty && <div className={styles.Empty}>None</div>}
{!isEmpty &&
(entries: any).map(([name, value]) => (
<KeyValue
key={name}
alphaSort={true}
bridge={bridge}
canDeletePaths={true}
canEditValues={true}
canRenamePaths={true}
depth={1}
element={element}
hidden={false}
inspectedElement={inspectedElement}
name={name}
path={[name]}
pathRoot="state"
store={store}
value={value}
/>
))}
return (
<div className={styles.InspectedElementTree}>
<div className={styles.HeaderRow}>
<div className={styles.Header}>state</div>
{!isEmpty && (
<Button onClick={handleCopy} title="Copy to clipboard">
<ButtonIcon type="copy" />
</Button>
)}
</div>
);
}
{isEmpty && <div className={styles.Empty}>None</div>}
{!isEmpty &&
(entries: any).map(([name, value]) => (
<KeyValue
key={name}
alphaSort={true}
bridge={bridge}
canDeletePaths={true}
canEditValues={true}
canRenamePaths={true}
depth={1}
element={element}
hidden={false}
inspectedElement={inspectedElement}
name={name}
path={[name]}
pathRoot="state"
store={store}
value={value}
/>
))}
</div>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -373,7 +373,7 @@ export default function ComponentsSettings(_: {}): React.Node {
<option value={ElementTypeFunction}>function</option>
<option value={ElementTypeForwardRef}>forward ref</option>
<option value={ElementTypeHostComponent}>
host (e.g. &lt;div&gt;)
dom nodes (e.g. &lt;div&gt;)
</option>
<option value={ElementTypeMemo}>memo</option>
<option value={ElementTypeOtherOrUnknown}>other</option>
Expand Down

0 comments on commit 18dff79

Please sign in to comment.