@samitouri / QOS-React-2 / commits / 0008bb00d7

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 };