mirror of
https://github.com/facebook/react.git
synced 2025-11-01 09:12:30 +00:00
Updated test code to include a deeply nested DIV
This commit is contained in:
@@ -0,0 +1,34 @@
|
||||
// @flow
|
||||
|
||||
import React, { Fragment } from 'react';
|
||||
|
||||
function wrapWithHoc(Component, index) {
|
||||
function HOC() {
|
||||
return <Component />;
|
||||
}
|
||||
HOC.displayName = `HOC-${index}`;
|
||||
return HOC;
|
||||
}
|
||||
|
||||
function wrapWithNested(Component, times) {
|
||||
for (let i = 0; i < times; i++) {
|
||||
Component = wrapWithHoc(Component, i);
|
||||
}
|
||||
|
||||
return Component;
|
||||
}
|
||||
|
||||
function Nested() {
|
||||
return <div>Deeply nested div</div>;
|
||||
}
|
||||
|
||||
const DeeplyNested = wrapWithNested(Nested, 100);
|
||||
|
||||
export default function DeeplyNestedComponents() {
|
||||
return (
|
||||
<Fragment>
|
||||
<h1>Deeply nested component</h1>
|
||||
<DeeplyNested />
|
||||
</Fragment>
|
||||
);
|
||||
}
|
||||
@@ -1,132 +0,0 @@
|
||||
// @flow
|
||||
|
||||
import React, {
|
||||
createContext,
|
||||
Component,
|
||||
Fragment,
|
||||
useCallback,
|
||||
useDebugValue,
|
||||
useEffect,
|
||||
useReducer,
|
||||
useState,
|
||||
} from 'react';
|
||||
import styles from './EditableProps.css';
|
||||
|
||||
const initialData = { foo: 'FOO', bar: 'BAR' };
|
||||
|
||||
function reducer(state, action) {
|
||||
switch (action.type) {
|
||||
case 'swap':
|
||||
return { foo: state.bar, bar: state.foo };
|
||||
default:
|
||||
throw new Error();
|
||||
}
|
||||
}
|
||||
|
||||
type StatefulFunctionProps = {| name: string |};
|
||||
|
||||
function StatefulFunction({ name }: StatefulFunctionProps) {
|
||||
const [count, updateCount] = useState(0);
|
||||
const debouncedCount = useDebounce(count, 1000);
|
||||
const handleUpdateCountClick = useCallback(() => updateCount(count + 1), [
|
||||
count,
|
||||
]);
|
||||
|
||||
const [data, dispatch] = useReducer(reducer, initialData);
|
||||
const handleUpdateReducerClick = useCallback(
|
||||
() => dispatch({ type: 'swap' }),
|
||||
[]
|
||||
);
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
<li>Name: {name}</li>
|
||||
<li>
|
||||
<button onClick={handleUpdateCountClick}>
|
||||
Debounced count: {debouncedCount}
|
||||
</button>
|
||||
</li>
|
||||
<li>
|
||||
Reducer state: foo "{data.foo}", bar "{data.bar}"
|
||||
</li>
|
||||
<li>
|
||||
<button onClick={handleUpdateReducerClick}>Swap reducer values</button>
|
||||
</li>
|
||||
</Fragment>
|
||||
);
|
||||
}
|
||||
|
||||
const BoolContext = createContext(true);
|
||||
BoolContext.displayName = 'BoolContext';
|
||||
|
||||
type Props = {| name: string, toggle: boolean |};
|
||||
type State = {| cities: Array<string>, state: string |};
|
||||
|
||||
class StatefulClass extends Component<Props, State> {
|
||||
static contextType = BoolContext;
|
||||
|
||||
state: State = {
|
||||
cities: ['San Francisco', 'San Jose'],
|
||||
state: 'California',
|
||||
};
|
||||
|
||||
handleChange = ({ target }) =>
|
||||
this.setState({
|
||||
state: target.value,
|
||||
});
|
||||
|
||||
render() {
|
||||
return (
|
||||
<Fragment>
|
||||
<li>Name: {this.props.name}</li>
|
||||
<li>Toggle: {this.props.toggle ? 'true' : 'false'}</li>
|
||||
<li>
|
||||
State: <input value={this.state.state} onChange={this.handleChange} />
|
||||
</li>
|
||||
<li>Cities: {this.state.cities.join(', ')}</li>
|
||||
<li>Context: {this.context ? 'true' : 'false'}</li>
|
||||
</Fragment>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default function EditableProps() {
|
||||
return (
|
||||
<div className={styles.App}>
|
||||
<div className={styles.Header}>Editable props</div>
|
||||
<ul>
|
||||
<StatefulClass name="Brian" toggle={true} />
|
||||
<StatefulFunction name="Brian" />
|
||||
</ul>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
// Below copied from https://usehooks.com/
|
||||
function useDebounce(value, delay) {
|
||||
// State and setters for debounced value
|
||||
const [debouncedValue, setDebouncedValue] = useState(value);
|
||||
|
||||
// Show the value in DevTools
|
||||
useDebugValue(debouncedValue);
|
||||
|
||||
useEffect(
|
||||
() => {
|
||||
// Update debounced value after delay
|
||||
const handler = setTimeout(() => {
|
||||
setDebouncedValue(value);
|
||||
}, delay);
|
||||
|
||||
// Cancel the timeout if value changes (also on delay change or unmount)
|
||||
// This is how we prevent debounced value from updating if value is changed ...
|
||||
// .. within the delay period. Timeout gets cleared and restarted.
|
||||
return () => {
|
||||
clearTimeout(handler);
|
||||
};
|
||||
},
|
||||
[value, delay] // Only re-call effect if value or delay changes
|
||||
);
|
||||
|
||||
return debouncedValue;
|
||||
}
|
||||
// Above copied from https://usehooks.com/
|
||||
@@ -1,5 +1,131 @@
|
||||
// @flow
|
||||
|
||||
import EditableProps from './EditableProps';
|
||||
import React, {
|
||||
createContext,
|
||||
Component,
|
||||
Fragment,
|
||||
useCallback,
|
||||
useDebugValue,
|
||||
useEffect,
|
||||
useReducer,
|
||||
useState,
|
||||
} from 'react';
|
||||
|
||||
export default EditableProps;
|
||||
const initialData = { foo: 'FOO', bar: 'BAR' };
|
||||
|
||||
function reducer(state, action) {
|
||||
switch (action.type) {
|
||||
case 'swap':
|
||||
return { foo: state.bar, bar: state.foo };
|
||||
default:
|
||||
throw new Error();
|
||||
}
|
||||
}
|
||||
|
||||
type StatefulFunctionProps = {| name: string |};
|
||||
|
||||
function StatefulFunction({ name }: StatefulFunctionProps) {
|
||||
const [count, updateCount] = useState(0);
|
||||
const debouncedCount = useDebounce(count, 1000);
|
||||
const handleUpdateCountClick = useCallback(() => updateCount(count + 1), [
|
||||
count,
|
||||
]);
|
||||
|
||||
const [data, dispatch] = useReducer(reducer, initialData);
|
||||
const handleUpdateReducerClick = useCallback(
|
||||
() => dispatch({ type: 'swap' }),
|
||||
[]
|
||||
);
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
<li>Name: {name}</li>
|
||||
<li>
|
||||
<button onClick={handleUpdateCountClick}>
|
||||
Debounced count: {debouncedCount}
|
||||
</button>
|
||||
</li>
|
||||
<li>
|
||||
Reducer state: foo "{data.foo}", bar "{data.bar}"
|
||||
</li>
|
||||
<li>
|
||||
<button onClick={handleUpdateReducerClick}>Swap reducer values</button>
|
||||
</li>
|
||||
</Fragment>
|
||||
);
|
||||
}
|
||||
|
||||
const BoolContext = createContext(true);
|
||||
BoolContext.displayName = 'BoolContext';
|
||||
|
||||
type Props = {| name: string, toggle: boolean |};
|
||||
type State = {| cities: Array<string>, state: string |};
|
||||
|
||||
class StatefulClass extends Component<Props, State> {
|
||||
static contextType = BoolContext;
|
||||
|
||||
state: State = {
|
||||
cities: ['San Francisco', 'San Jose'],
|
||||
state: 'California',
|
||||
};
|
||||
|
||||
handleChange = ({ target }) =>
|
||||
this.setState({
|
||||
state: target.value,
|
||||
});
|
||||
|
||||
render() {
|
||||
return (
|
||||
<Fragment>
|
||||
<li>Name: {this.props.name}</li>
|
||||
<li>Toggle: {this.props.toggle ? 'true' : 'false'}</li>
|
||||
<li>
|
||||
State: <input value={this.state.state} onChange={this.handleChange} />
|
||||
</li>
|
||||
<li>Cities: {this.state.cities.join(', ')}</li>
|
||||
<li>Context: {this.context ? 'true' : 'false'}</li>
|
||||
</Fragment>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default function EditableProps() {
|
||||
return (
|
||||
<Fragment>
|
||||
<h1>Editable props</h1>
|
||||
<ul>
|
||||
<StatefulClass name="Brian" toggle={true} />
|
||||
<StatefulFunction name="Brian" />
|
||||
</ul>
|
||||
</Fragment>
|
||||
);
|
||||
}
|
||||
|
||||
// Below copied from https://usehooks.com/
|
||||
function useDebounce(value, delay) {
|
||||
// State and setters for debounced value
|
||||
const [debouncedValue, setDebouncedValue] = useState(value);
|
||||
|
||||
// Show the value in DevTools
|
||||
useDebugValue(debouncedValue);
|
||||
|
||||
useEffect(
|
||||
() => {
|
||||
// Update debounced value after delay
|
||||
const handler = setTimeout(() => {
|
||||
setDebouncedValue(value);
|
||||
}, delay);
|
||||
|
||||
// Cancel the timeout if value changes (also on delay change or unmount)
|
||||
// This is how we prevent debounced value from updating if value is changed ...
|
||||
// .. within the delay period. Timeout gets cleared and restarted.
|
||||
return () => {
|
||||
clearTimeout(handler);
|
||||
};
|
||||
},
|
||||
[value, delay] // Only re-call effect if value or delay changes
|
||||
);
|
||||
|
||||
return debouncedValue;
|
||||
}
|
||||
// Above copied from https://usehooks.com/
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
.App {
|
||||
/* GitHub.com frontend fonts */
|
||||
font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Helvetica, Arial,
|
||||
sans-serif, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol;
|
||||
font-size: 14px;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.Header {
|
||||
font-size: 1.5rem;
|
||||
font-weight: bold;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
@@ -1,20 +1,19 @@
|
||||
// @flow
|
||||
|
||||
import React from 'react';
|
||||
import React, { Fragment } from 'react';
|
||||
import Contexts from './Contexts';
|
||||
import CustomHooks from './CustomHooks';
|
||||
import NestedProps from './NestedProps';
|
||||
import styles from './InspectableElements.css';
|
||||
|
||||
// TODO Add Immutable JS example
|
||||
|
||||
export default function InspectableElements() {
|
||||
return (
|
||||
<div className={styles.App}>
|
||||
<div className={styles.Header}>Inspectable elements</div>
|
||||
<Fragment>
|
||||
<h1>Inspectable elements</h1>
|
||||
<NestedProps />
|
||||
<Contexts />
|
||||
<CustomHooks />
|
||||
</div>
|
||||
</Fragment>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,17 +1,3 @@
|
||||
.App {
|
||||
/* GitHub.com frontend fonts */
|
||||
font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Helvetica, Arial,
|
||||
sans-serif, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol;
|
||||
font-size: 14px;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.Header {
|
||||
font-size: 1.5rem;
|
||||
font-weight: bold;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.Input {
|
||||
font-size: 1rem;
|
||||
padding: 0.25rem;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// @flow
|
||||
|
||||
import React, { useCallback, useState } from 'react';
|
||||
import React, { Fragment, useCallback, useState } from 'react';
|
||||
import ListItem from './ListItem';
|
||||
import styles from './List.css';
|
||||
|
||||
@@ -77,8 +77,8 @@ export default function List(props: Props) {
|
||||
);
|
||||
|
||||
return (
|
||||
<div className={styles.App}>
|
||||
<div className={styles.Header}>List</div>
|
||||
<Fragment>
|
||||
<h1>List</h1>
|
||||
<input
|
||||
type="text"
|
||||
placeholder="New list item..."
|
||||
@@ -106,6 +106,6 @@ export default function List(props: Props) {
|
||||
/>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
</Fragment>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -4,11 +4,14 @@
|
||||
|
||||
import { createElement } from 'react';
|
||||
import { render, unmountComponentAtNode } from 'react-dom';
|
||||
import DeeplyNestedComponents from './DeeplyNestedComponents';
|
||||
import EditableProps from './EditableProps';
|
||||
import ElementTypes from './ElementTypes';
|
||||
import InspectableElements from './InspectableElements';
|
||||
import ToDoList from './ToDoList';
|
||||
|
||||
import './styles.css';
|
||||
|
||||
const containers = [];
|
||||
|
||||
function mountHelper(App) {
|
||||
@@ -26,6 +29,7 @@ function mountTestApp() {
|
||||
mountHelper(InspectableElements);
|
||||
mountHelper(ElementTypes);
|
||||
mountHelper(EditableProps);
|
||||
mountHelper(DeeplyNestedComponents);
|
||||
}
|
||||
|
||||
function unmountTestApp() {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
.App {
|
||||
body {
|
||||
/* GitHub.com frontend fonts */
|
||||
font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Helvetica, Arial,
|
||||
sans-serif, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol;
|
||||
@@ -6,7 +6,7 @@
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.Header {
|
||||
h1 {
|
||||
font-size: 1.5rem;
|
||||
font-weight: bold;
|
||||
margin-bottom: 0.5rem;
|
||||
@@ -1,6 +1,13 @@
|
||||
// @flow
|
||||
|
||||
import React, { Fragment, useCallback, useContext, useEffect, useMemo, useRef } from 'react';
|
||||
import React, {
|
||||
Fragment,
|
||||
useCallback,
|
||||
useContext,
|
||||
useEffect,
|
||||
useMemo,
|
||||
useRef,
|
||||
} from 'react';
|
||||
import { ElementTypeClass, ElementTypeFunction } from 'src/devtools/types';
|
||||
import { createRegExp } from './utils';
|
||||
import { TreeContext } from './TreeContext';
|
||||
@@ -26,6 +33,7 @@ export default function ElementView({ index, style }: Props) {
|
||||
const element = getElementAtIndex(index);
|
||||
|
||||
const id = element === null ? null : element.id;
|
||||
const isSelected = selectedElementID === id;
|
||||
|
||||
const handleDoubleClick = useCallback(() => {
|
||||
if (id !== null) {
|
||||
@@ -33,7 +41,7 @@ export default function ElementView({ index, style }: Props) {
|
||||
}
|
||||
}, [id, selectOwner]);
|
||||
|
||||
const ref = useRef();
|
||||
const ref = useRef<HTMLSpanElement | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
if (isSelected) {
|
||||
@@ -64,7 +72,6 @@ export default function ElementView({ index, style }: Props) {
|
||||
|
||||
const { depth, displayName, key, type } = ((element: any): Element);
|
||||
|
||||
const isSelected = selectedElementID === id;
|
||||
const showDollarR =
|
||||
isSelected && (type === ElementTypeClass || type === ElementTypeFunction);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user