Updated test code to include a deeply nested DIV
Brian Vaughn committed
Feb 27, 2019 at 13:05 UTC
bc4e8950f6d0d33399b9b86fdc9129ca0d5d2295
10 files changed
+186
-175
shells/dev/app/DeeplyNestedComponents/index.js
new
+34
@@ -0,0 +1,34 @@
1
+// @flow
2
+
3
+import React, { Fragment } from 'react';
4
+
5
+function wrapWithHoc(Component, index) {
6
+ function HOC() {
7
+ return <Component />;
8
+ }
9
+ HOC.displayName = `HOC-${index}`;
10
+ return HOC;
11
+}
12
+
13
+function wrapWithNested(Component, times) {
14
+ for (let i = 0; i < times; i++) {
15
+ Component = wrapWithHoc(Component, i);
16
+ }
17
+
18
+ return Component;
19
+}
20
+
21
+function Nested() {
22
+ return <div>Deeply nested div</div>;
23
+}
24
+
25
+const DeeplyNested = wrapWithNested(Nested, 100);
26
+
27
+export default function DeeplyNestedComponents() {
28
+ return (
29
+ <Fragment>
30
+ <h1>Deeply nested component</h1>
31
+ <DeeplyNested />
32
+ </Fragment>
33
+ );
34
+}
shells/dev/app/EditableProps/EditableProps.js
deleted
-132
@@ -1,132 +0,0 @@
1
-// @flow
2
-
3
-import React, {
4
- createContext,
5
- Component,
6
- Fragment,
7
- useCallback,
8
- useDebugValue,
9
- useEffect,
10
- useReducer,
11
- useState,
12
-} from 'react';
13
-import styles from './EditableProps.css';
14
-
15
-const initialData = { foo: 'FOO', bar: 'BAR' };
16
-
17
-function reducer(state, action) {
18
- switch (action.type) {
19
- case 'swap':
20
- return { foo: state.bar, bar: state.foo };
21
- default:
22
- throw new Error();
23
- }
24
-}
25
-
26
-type StatefulFunctionProps = {| name: string |};
27
-
28
-function StatefulFunction({ name }: StatefulFunctionProps) {
29
- const [count, updateCount] = useState(0);
30
- const debouncedCount = useDebounce(count, 1000);
31
- const handleUpdateCountClick = useCallback(() => updateCount(count + 1), [
32
- count,
33
- ]);
34
-
35
- const [data, dispatch] = useReducer(reducer, initialData);
36
- const handleUpdateReducerClick = useCallback(
37
- () => dispatch({ type: 'swap' }),
38
- []
39
- );
40
-
41
- return (
42
- <Fragment>
43
- <li>Name: {name}</li>
44
- <li>
45
- <button onClick={handleUpdateCountClick}>
46
- Debounced count: {debouncedCount}
47
- </button>
48
- </li>
49
- <li>
50
- Reducer state: foo "{data.foo}", bar "{data.bar}"
51
- </li>
52
- <li>
53
- <button onClick={handleUpdateReducerClick}>Swap reducer values</button>
54
- </li>
55
- </Fragment>
56
- );
57
-}
58
-
59
-const BoolContext = createContext(true);
60
-BoolContext.displayName = 'BoolContext';
61
-
62
-type Props = {| name: string, toggle: boolean |};
63
-type State = {| cities: Array<string>, state: string |};
64
-
65
-class StatefulClass extends Component<Props, State> {
66
- static contextType = BoolContext;
67
-
68
- state: State = {
69
- cities: ['San Francisco', 'San Jose'],
70
- state: 'California',
71
- };
72
-
73
- handleChange = ({ target }) =>
74
- this.setState({
75
- state: target.value,
76
- });
77
-
78
- render() {
79
- return (
80
- <Fragment>
81
- <li>Name: {this.props.name}</li>
82
- <li>Toggle: {this.props.toggle ? 'true' : 'false'}</li>
83
- <li>
84
- State: <input value={this.state.state} onChange={this.handleChange} />
85
- </li>
86
- <li>Cities: {this.state.cities.join(', ')}</li>
87
- <li>Context: {this.context ? 'true' : 'false'}</li>
88
- </Fragment>
89
- );
90
- }
91
-}
92
-
93
-export default function EditableProps() {
94
- return (
95
- <div className={styles.App}>
96
- <div className={styles.Header}>Editable props</div>
97
- <ul>
98
- <StatefulClass name="Brian" toggle={true} />
99
- <StatefulFunction name="Brian" />
100
- </ul>
101
- </div>
102
- );
103
-}
104
-
105
-// Below copied from https://usehooks.com/
106
-function useDebounce(value, delay) {
107
- // State and setters for debounced value
108
- const [debouncedValue, setDebouncedValue] = useState(value);
109
-
110
- // Show the value in DevTools
111
- useDebugValue(debouncedValue);
112
-
113
- useEffect(
114
- () => {
115
- // Update debounced value after delay
116
- const handler = setTimeout(() => {
117
- setDebouncedValue(value);
118
- }, delay);
119
-
120
- // Cancel the timeout if value changes (also on delay change or unmount)
121
- // This is how we prevent debounced value from updating if value is changed ...
122
- // .. within the delay period. Timeout gets cleared and restarted.
123
- return () => {
124
- clearTimeout(handler);
125
- };
126
- },
127
- [value, delay] // Only re-call effect if value or delay changes
128
- );
129
-
130
- return debouncedValue;
131
-}
132
-// Above copied from https://usehooks.com/
shells/dev/app/EditableProps/index.js
+128
-2
@@ -1,5 +1,131 @@
1
// @flow
2
3
-import EditableProps from './EditableProps';
3
+import React, {
4
+ createContext,
5
+ Component,
6
+ Fragment,
7
+ useCallback,
8
+ useDebugValue,
9
+ useEffect,
10
+ useReducer,
11
+ useState,
12
+} from 'react';
13
5
-export default EditableProps;
14
+const initialData = { foo: 'FOO', bar: 'BAR' };
15
+
16
+function reducer(state, action) {
17
+ switch (action.type) {
18
+ case 'swap':
19
+ return { foo: state.bar, bar: state.foo };
20
+ default:
21
+ throw new Error();
22
+ }
23
+}
24
+
25
+type StatefulFunctionProps = {| name: string |};
26
+
27
+function StatefulFunction({ name }: StatefulFunctionProps) {
28
+ const [count, updateCount] = useState(0);
29
+ const debouncedCount = useDebounce(count, 1000);
30
+ const handleUpdateCountClick = useCallback(() => updateCount(count + 1), [
31
+ count,
32
+ ]);
33
+
34
+ const [data, dispatch] = useReducer(reducer, initialData);
35
+ const handleUpdateReducerClick = useCallback(
36
+ () => dispatch({ type: 'swap' }),
37
+ []
38
+ );
39
+
40
+ return (
41
+ <Fragment>
42
+ <li>Name: {name}</li>
43
+ <li>
44
+ <button onClick={handleUpdateCountClick}>
45
+ Debounced count: {debouncedCount}
46
+ </button>
47
+ </li>
48
+ <li>
49
+ Reducer state: foo "{data.foo}", bar "{data.bar}"
50
+ </li>
51
+ <li>
52
+ <button onClick={handleUpdateReducerClick}>Swap reducer values</button>
53
+ </li>
54
+ </Fragment>
55
+ );
56
+}
57
+
58
+const BoolContext = createContext(true);
59
+BoolContext.displayName = 'BoolContext';
60
+
61
+type Props = {| name: string, toggle: boolean |};
62
+type State = {| cities: Array<string>, state: string |};
63
+
64
+class StatefulClass extends Component<Props, State> {
65
+ static contextType = BoolContext;
66
+
67
+ state: State = {
68
+ cities: ['San Francisco', 'San Jose'],
69
+ state: 'California',
70
+ };
71
+
72
+ handleChange = ({ target }) =>
73
+ this.setState({
74
+ state: target.value,
75
+ });
76
+
77
+ render() {
78
+ return (
79
+ <Fragment>
80
+ <li>Name: {this.props.name}</li>
81
+ <li>Toggle: {this.props.toggle ? 'true' : 'false'}</li>
82
+ <li>
83
+ State: <input value={this.state.state} onChange={this.handleChange} />
84
+ </li>
85
+ <li>Cities: {this.state.cities.join(', ')}</li>
86
+ <li>Context: {this.context ? 'true' : 'false'}</li>
87
+ </Fragment>
88
+ );
89
+ }
90
+}
91
+
92
+export default function EditableProps() {
93
+ return (
94
+ <Fragment>
95
+ <h1>Editable props</h1>
96
+ <ul>
97
+ <StatefulClass name="Brian" toggle={true} />
98
+ <StatefulFunction name="Brian" />
99
+ </ul>
100
+ </Fragment>
101
+ );
102
+}
103
+
104
+// Below copied from https://usehooks.com/
105
+function useDebounce(value, delay) {
106
+ // State and setters for debounced value
107
+ const [debouncedValue, setDebouncedValue] = useState(value);
108
+
109
+ // Show the value in DevTools
110
+ useDebugValue(debouncedValue);
111
+
112
+ useEffect(
113
+ () => {
114
+ // Update debounced value after delay
115
+ const handler = setTimeout(() => {
116
+ setDebouncedValue(value);
117
+ }, delay);
118
+
119
+ // Cancel the timeout if value changes (also on delay change or unmount)
120
+ // This is how we prevent debounced value from updating if value is changed ...
121
+ // .. within the delay period. Timeout gets cleared and restarted.
122
+ return () => {
123
+ clearTimeout(handler);
124
+ };
125
+ },
126
+ [value, delay] // Only re-call effect if value or delay changes
127
+ );
128
+
129
+ return debouncedValue;
130
+}
131
+// Above copied from https://usehooks.com/
shells/dev/app/InspectableElements/InspectableElements.css
deleted
-13
@@ -1,13 +0,0 @@
1
-.App {
2
- /* GitHub.com frontend fonts */
3
- font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Helvetica, Arial,
4
- sans-serif, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol;
5
- font-size: 14px;
6
- line-height: 1.5;
7
-}
8
-
9
-.Header {
10
- font-size: 1.5rem;
11
- font-weight: bold;
12
- margin-bottom: 0.5rem;
13
-}
shells/dev/app/InspectableElements/InspectableElements.js
+4
-5
@@ -1,20 +1,19 @@
1
// @flow
2
3
-import React from 'react';
3
+import React, { Fragment } from 'react';
4
import Contexts from './Contexts';
5
import CustomHooks from './CustomHooks';
6
import NestedProps from './NestedProps';
7
-import styles from './InspectableElements.css';
7
8
// TODO Add Immutable JS example
9
10
export default function InspectableElements() {
11
return (
13
- <div className={styles.App}>
14
- <div className={styles.Header}>Inspectable elements</div>
12
+ <Fragment>
13
+ <h1>Inspectable elements</h1>
14
<NestedProps />
15
<Contexts />
16
<CustomHooks />
18
- </div>
17
+ </Fragment>
18
);
19
}
shells/dev/app/ToDoList/List.css
-14
@@ -1,17 +1,3 @@
1
-.App {
2
- /* GitHub.com frontend fonts */
3
- font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Helvetica, Arial,
4
- sans-serif, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol;
5
- font-size: 14px;
6
- line-height: 1.5;
7
-}
8
-
9
-.Header {
10
- font-size: 1.5rem;
11
- font-weight: bold;
12
- margin-bottom: 0.5rem;
13
-}
14
-
1
.Input {
2
font-size: 1rem;
3
padding: 0.25rem;
shells/dev/app/ToDoList/List.js
+4
-4
@@ -1,6 +1,6 @@
1
// @flow
2
3
-import React, { useCallback, useState } from 'react';
3
+import React, { Fragment, useCallback, useState } from 'react';
4
import ListItem from './ListItem';
5
import styles from './List.css';
6
@@ -77,8 +77,8 @@ export default function List(props: Props) {
77
);
78
79
return (
80
- <div className={styles.App}>
81
- <div className={styles.Header}>List</div>
80
+ <Fragment>
81
+ <h1>List</h1>
82
<input
83
type="text"
84
placeholder="New list item..."
@@ -106,6 +106,6 @@ export default function List(props: Props) {
106
/>
107
))}
108
</ul>
109
- </div>
109
+ </Fragment>
110
);
111
}
shells/dev/app/index.js
+4
@@ -4,11 +4,14 @@
4
5
import { createElement } from 'react';
6
import { render, unmountComponentAtNode } from 'react-dom';
7
+import DeeplyNestedComponents from './DeeplyNestedComponents';
8
import EditableProps from './EditableProps';
9
import ElementTypes from './ElementTypes';
10
import InspectableElements from './InspectableElements';
11
import ToDoList from './ToDoList';
12
13
+import './styles.css';
14
+
15
const containers = [];
16
17
function mountHelper(App) {
@@ -26,6 +29,7 @@ function mountTestApp() {
29
mountHelper(InspectableElements);
30
mountHelper(ElementTypes);
31
mountHelper(EditableProps);
32
+ mountHelper(DeeplyNestedComponents);
33
}
34
35
function unmountTestApp() {
shells/dev/app/styles.css
renamed
+2
-2
@@ -1,4 +1,4 @@
1
-.App {
1
+body {
2
/* GitHub.com frontend fonts */
3
font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Helvetica, Arial,
4
sans-serif, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol;
@@ -6,7 +6,7 @@
6
line-height: 1.5;
7
}
8
9
-.Header {
9
+h1 {
10
font-size: 1.5rem;
11
font-weight: bold;
12
margin-bottom: 0.5rem;
src/devtools/views/Element.js
+10
-3
@@ -1,6 +1,13 @@
1
// @flow
2
3
-import React, { Fragment, useCallback, useContext, useEffect, useMemo, useRef } from 'react';
3
+import React, {
4
+ Fragment,
5
+ useCallback,
6
+ useContext,
7
+ useEffect,
8
+ useMemo,
9
+ useRef,
10
+} from 'react';
11
import { ElementTypeClass, ElementTypeFunction } from 'src/devtools/types';
12
import { createRegExp } from './utils';
13
import { TreeContext } from './TreeContext';
@@ -26,6 +33,7 @@ export default function ElementView({ index, style }: Props) {
33
const element = getElementAtIndex(index);
34
35
const id = element === null ? null : element.id;
36
+ const isSelected = selectedElementID === id;
37
38
const handleDoubleClick = useCallback(() => {
39
if (id !== null) {
@@ -33,7 +41,7 @@ export default function ElementView({ index, style }: Props) {
41
}
42
}, [id, selectOwner]);
43
36
- const ref = useRef();
44
+ const ref = useRef<HTMLSpanElement | null>(null);
45
46
useEffect(() => {
47
if (isSelected) {
@@ -64,7 +72,6 @@ export default function ElementView({ index, style }: Props) {
72
73
const { depth, displayName, key, type } = ((element: any): Element);
74
67
- const isSelected = selectedElementID === id;
75
const showDollarR =
76
isSelected && (type === ElementTypeClass || type === ElementTypeFunction);
77