Inspectable complex hook values
Brian Vaughn committed
Feb 14, 2019 at 21:55 UTC
0008bb00d7fc2bf2fc3493679434bc1ff2d01f18
4 files changed
+84
-24
shells/dev/app/InspectableElements/CustomHooks.js
+18
@@ -11,6 +11,16 @@ import React, {
11
useState,
12
} from 'react';
13
14
+const object = {
15
+ string: 'abc',
16
+ number: 123,
17
+ boolean: true,
18
+ null: null,
19
+ undefined: undefined,
20
+ array: ['a', 'b', 'c'],
21
+ object: { foo: 1, bar: 2, baz: 3 },
22
+};
23
+
24
function useNestedInnerHook() {
25
return useState(123);
26
}
@@ -18,12 +28,20 @@ function useNestedOuterHook() {
28
return useNestedInnerHook();
29
}
30
31
+function useCustomObject() {
32
+ useDebugValue(object);
33
+ return useState(123);
34
+}
35
+
36
function FunctionWithHooks(props: any, ref: React$Ref<any>) {
37
const [count, updateCount] = useState(0);
38
+ const [_, __] = useState(object);
39
40
// Custom hook with a custom debug label
41
const debouncedCount = useDebounce(count, 1000);
42
43
+ useCustomObject();
44
+
45
const onClick = useCallback(
46
function onClick() {
47
updateCount(count + 1);
src/devtools/views/HooksTree.js
+57
-20
@@ -2,6 +2,7 @@
2
3
import React from 'react';
4
import { getMetaValueLabel } from './utils';
5
+import { KeyValue } from './InspectedElementTree';
6
import styles from './HooksTree.css';
7
8
import type { HooksNode, HooksTree } from 'src/backend/types';
@@ -34,31 +35,67 @@ function HooksNodeView({ hooksNode }: { hooksNode: HooksNode }) {
35
36
const isCustomHook = subHooks.length > 0;
37
37
- // Format data for display to mimic the props/state/context for now.
38
const type = typeof value;
39
+
40
let displayValue;
40
- if (isCustomHook && value === undefined) {
41
- displayValue = null;
42
- } else if (
43
- type === 'number' ||
44
- type === 'string' ||
45
- type === 'boolean' ||
46
- value == null
47
- ) {
41
+ let isComplexDisplayValue = false;
42
+
43
+ // Format data for display to mimic the props/state/context for now.
44
+ if (type === 'number' || type === 'string' || type === 'boolean') {
45
displayValue = value;
49
- } else {
50
- displayValue = getMetaValueLabel(value);
46
+ } else if (value === null) {
47
+ displayValue = 'null';
48
+ } else if (value === undefined) {
49
+ displayValue = null;
50
+ } else if (Array.isArray(value)) {
51
+ isComplexDisplayValue = true;
52
+ displayValue = 'Array';
53
+ } else if (type === 'object') {
54
+ isComplexDisplayValue = true;
55
+ displayValue = 'Object';
56
}
57
53
- return (
54
- <div className={styles.HooksNode}>
55
- <div className={styles.NameValueRow}>
56
- <span className={styles.Name}>{name}: </span> {/* $FlowFixMe */}
57
- <span className={styles.Value}>{displayValue}</span>
58
- </div>
59
- <InnerHooksTreeView hooksTree={subHooks} />
60
- </div>
61
- );
58
+ if (isCustomHook) {
59
+ if (isComplexDisplayValue) {
60
+ return (
61
+ <div className={styles.HooksNode}>
62
+ <div className={styles.NameValueRow}>
63
+ <span className={styles.Name}>{name}: </span>
64
+ </div>
65
+ <KeyValue depth={1} name="DebugValue" value={value} />
66
+ <InnerHooksTreeView hooksTree={subHooks} />
67
+ </div>
68
+ );
69
+ } else {
70
+ return (
71
+ <div className={styles.HooksNode}>
72
+ <div className={styles.NameValueRow}>
73
+ <span className={styles.Name}>{name}: </span> {/* $FlowFixMe */}
74
+ <span className={styles.Value}>{displayValue}</span>
75
+ </div>
76
+ <InnerHooksTreeView hooksTree={subHooks} />
77
+ </div>
78
+ );
79
+ }
80
+ } else {
81
+ if (isComplexDisplayValue) {
82
+ return (
83
+ <div className={styles.HooksNode}>
84
+ <KeyValue depth={0} name={name} value={value} />
85
+ </div>
86
+ );
87
+ } else {
88
+ return (
89
+ <div className={styles.HooksNode}>
90
+ <div className={styles.NameValueRow}>
91
+ <span className={styles.Name}>{name}: </span>
92
+ {/* $FlowFixMe */}
93
+ <span className={styles.Value}>{displayValue}</span>
94
+ </div>
95
+ </div>
96
+ );
97
+ }
98
+ }
99
}
100
101
// $FlowFixMe
src/devtools/views/InspectedElementTree.js
+6
-1
@@ -47,7 +47,7 @@ type KeyValueProps = {|
47
value: any,
48
|};
49
50
-function KeyValue({ depth, name, value }: KeyValueProps) {
50
+export function KeyValue({ depth, name, value }: KeyValueProps) {
51
const dataType = typeof value;
52
const isSimpleType =
53
dataType === 'number' ||
@@ -64,6 +64,10 @@ function KeyValue({ depth, name, value }: KeyValueProps) {
64
displayValue = `"${value}"`;
65
} else if (dataType === 'boolean') {
66
displayValue = value ? 'true' : 'false';
67
+ } else if (value === null) {
68
+ displayValue = 'null';
69
+ } else if (value === undefined) {
70
+ displayValue = 'undefined';
71
}
72
73
children = (
@@ -99,6 +103,7 @@ function KeyValue({ depth, name, value }: KeyValueProps) {
103
</div>
104
);
105
} else {
106
+ // $FlowFixMe
107
children = Object.entries(value).map(([name, value]) => (
108
<KeyValue key={name} depth={depth + 1} name={name} value={value} />
109
));
src/devtools/views/SettingsContext.js
+3
-3
@@ -132,13 +132,13 @@ function updateThemeVariables(theme: Theme): void {
132
updateStyleHelper(theme, 'color-dim');
133
updateStyleHelper(theme, 'color-dimmer');
134
updateStyleHelper(theme, 'color-dimmest');
135
- updateStyleHelper(theme, 'color-search-match');
136
- updateStyleHelper(theme, 'color-search-match-current');
137
- updateStyleHelper(theme, 'color-text-color');
135
updateStyleHelper(theme, 'color-jsx-arrow-brackets');
136
updateStyleHelper(theme, 'color-jsx-arrow-brackets-inverted');
137
updateStyleHelper(theme, 'color-tree-node-selected');
138
updateStyleHelper(theme, 'color-tree-node-hover');
139
+ updateStyleHelper(theme, 'color-search-match');
140
+ updateStyleHelper(theme, 'color-search-match-current');
141
+ updateStyleHelper(theme, 'color-text-color');
142
}
143
144
export { SettingsContext, SettingsContextController };