diff --git a/.prettierrc.js b/.prettierrc.js index df8d863ae4c09..6e5dcb710f0f0 100644 --- a/.prettierrc.js +++ b/.prettierrc.js @@ -8,7 +8,7 @@ module.exports = { jsxBracketSameLine: true, trailingComma: 'es5', printWidth: 80, - parser: 'babylon', + parser: 'babel', overrides: [ { diff --git a/fixtures/attribute-behavior/src/App.js b/fixtures/attribute-behavior/src/App.js index 3764349b958a7..7cb678b587389 100644 --- a/fixtures/attribute-behavior/src/App.js +++ b/fixtures/attribute-behavior/src/App.js @@ -461,9 +461,7 @@ function prepareState(initGlobals) { hasSameBehaviorForAll, rowPatternHash, // "Good enough" id that we can store in localStorage - rowIdHash: `${attribute.name} ${attribute.tagName} ${ - attribute.overrideStringValue - }`, + rowIdHash: `${attribute.name} ${attribute.tagName} ${attribute.overrideStringValue}`, }; const rowGroup = rowPatternHashes.get(rowPatternHash) || new Set(); rowGroup.add(row); @@ -866,14 +864,12 @@ class App extends React.Component { // Sort switch (sortOrder) { case ALPHABETICAL: - return filteredAttributes.sort( - (attr1, attr2) => - attr1.name.toLowerCase() < attr2.name.toLowerCase() ? -1 : 1 + return filteredAttributes.sort((attr1, attr2) => + attr1.name.toLowerCase() < attr2.name.toLowerCase() ? -1 : 1 ); case REV_ALPHABETICAL: - return filteredAttributes.sort( - (attr1, attr2) => - attr1.name.toLowerCase() < attr2.name.toLowerCase() ? 1 : -1 + return filteredAttributes.sort((attr1, attr2) => + attr1.name.toLowerCase() < attr2.name.toLowerCase() ? 1 : -1 ); case GROUPED_BY_ROW_PATTERN: { return filteredAttributes.sort((attr1, attr2) => { diff --git a/fixtures/dom/src/components/Iframe.js b/fixtures/dom/src/components/Iframe.js index 3030d5059453e..b69f74ef3ae8e 100644 --- a/fixtures/dom/src/components/Iframe.js +++ b/fixtures/dom/src/components/Iframe.js @@ -55,4 +55,4 @@ class IframeSubtree extends React.Component { } } -export default (ReactDOM.createPortal ? IframePortal : IframeSubtree); +export default ReactDOM.createPortal ? IframePortal : IframeSubtree; diff --git a/fixtures/dom/src/components/fixtures/home.js b/fixtures/dom/src/components/fixtures/home.js index b2f04ef272588..b446cf7e613d2 100644 --- a/fixtures/dom/src/components/fixtures/home.js +++ b/fixtures/dom/src/components/fixtures/home.js @@ -33,7 +33,8 @@ export default function Home() { ESR - , Latest + + , Latest diff --git a/fixtures/dom/src/components/fixtures/suspense/index.js b/fixtures/dom/src/components/fixtures/suspense/index.js index 44b9f33192c97..ce4c64f30e8ab 100644 --- a/fixtures/dom/src/components/fixtures/suspense/index.js +++ b/fixtures/dom/src/components/fixtures/suspense/index.js @@ -213,8 +213,8 @@ class TextInputFixtures extends React.Component { - React - is cool + + React is cool @@ -308,7 +308,9 @@ class TextInputFixtures extends React.Component {
{Array(20) .fill() - .map((_, i) =>

{i + 1}

)} + .map((_, i) => ( +

{i + 1}

+ ))}
diff --git a/fixtures/dom/src/toWarnDev.js b/fixtures/dom/src/toWarnDev.js index ab4424d735b38..faa793f416c40 100644 --- a/fixtures/dom/src/toWarnDev.js +++ b/fixtures/dom/src/toWarnDev.js @@ -205,9 +205,7 @@ const createMatcherFor = consoleMethod => if (withoutStack !== warningsWithoutComponentStack.length) { return { message: () => - `Expected ${withoutStack} warnings without a component stack but received ${ - warningsWithoutComponentStack.length - }:\n` + + `Expected ${withoutStack} warnings without a component stack but received ${warningsWithoutComponentStack.length}:\n` + warningsWithoutComponentStack.map(warning => this.utils.printReceived(warning) ), diff --git a/fixtures/eslint/index.js b/fixtures/eslint/index.js index 1052cac180fcc..d53415310560d 100644 --- a/fixtures/eslint/index.js +++ b/fixtures/eslint/index.js @@ -8,22 +8,19 @@ function Comment({comment, commentSource}) { const currentUserID = comment.viewer.id; const environment = RelayEnvironment.forUser(currentUserID); const commentID = nullthrows(comment.id); - useEffect( - () => { - const subscription = SubscriptionCounter.subscribeOnce( - `StoreSubscription_${commentID}`, - () => - StoreSubscription.subscribe( - environment, - { - comment_id: commentID, - }, - currentUserID, - commentSource - ) - ); - return () => subscription.dispose(); - }, - [commentID, commentSource, currentUserID, environment] - ); + useEffect(() => { + const subscription = SubscriptionCounter.subscribeOnce( + `StoreSubscription_${commentID}`, + () => + StoreSubscription.subscribe( + environment, + { + comment_id: commentID, + }, + currentUserID, + commentSource + ) + ); + return () => subscription.dispose(); + }, [commentID, commentSource, currentUserID, environment]); } diff --git a/fixtures/fiber-debugger/src/App.js b/fixtures/fiber-debugger/src/App.js index a70e3aee5df8d..75d74c76b70cd 100644 --- a/fixtures/fiber-debugger/src/App.js +++ b/fixtures/fiber-debugger/src/App.js @@ -192,8 +192,7 @@ class App extends Component { } />

- Step {currentStep} - : {friendlyAction} ( + Step {currentStep}: {friendlyAction} ( Edit diff --git a/fixtures/fiber-debugger/src/Fibers.js b/fixtures/fiber-debugger/src/Fibers.js index bd5d1b742ceed..b6b06e59a7170 100644 --- a/fixtures/fiber-debugger/src/Fibers.js +++ b/fixtures/fiber-debugger/src/Fibers.js @@ -330,83 +330,76 @@ export default function Fibers({fibers, show, graphSettings, ...rest}) { ]} , - fiber.child && - show.child && ( - - child - - ), - fiber.sibling && - show.sibling && ( - - sibling - - ), - fiber.return && - show.return && ( - - return - - ), - fiber.nextEffect && - show.fx && ( - - nextFx - - ), - fiber.firstEffect && - show.fx && ( - - firstFx - - ), - fiber.lastEffect && - show.fx && ( - - lastFx - - ), - fiber.alternate && - show.alt && ( - - alt - - ), + fiber.child && show.child && ( + + child + + ), + fiber.sibling && show.sibling && ( + + sibling + + ), + fiber.return && show.return && ( + + return + + ), + fiber.nextEffect && show.fx && ( + + nextFx + + ), + fiber.firstEffect && show.fx && ( + + firstFx + + ), + fiber.lastEffect && show.fx && ( + + lastFx + + ), + fiber.alternate && show.alt && ( + + alt + + ), ])} diff --git a/package.json b/package.json index dde368a682c31..356b8fb7bf068 100644 --- a/package.json +++ b/package.json @@ -71,7 +71,7 @@ "ncp": "^2.0.0", "object-assign": "^4.1.1", "pacote": "^9.5.6", - "prettier": "1.13.7", + "prettier": "1.19.1", "prop-types": "^15.6.2", "random-seed": "^0.3.0", "react-lifecycles-compat": "^3.0.2", diff --git a/packages/create-subscription/src/__tests__/createSubscription-test.internal.js b/packages/create-subscription/src/__tests__/createSubscription-test.internal.js index fd74298c59572..cd924069ab393 100644 --- a/packages/create-subscription/src/__tests__/createSubscription-test.internal.js +++ b/packages/create-subscription/src/__tests__/createSubscription-test.internal.js @@ -118,7 +118,10 @@ describe('createSubscription', () => { const Subscription = createSubscription({ getCurrentValue: source => undefined, subscribe: (source, callback) => { - source.then(value => callback(value), value => callback(value)); + source.then( + value => callback(value), + value => callback(value), + ); // (Can't unsubscribe from a Promise) return () => {}; }, @@ -196,7 +199,10 @@ describe('createSubscription', () => { const Subscription = createSubscription({ getCurrentValue: source => undefined, subscribe: (source, callback) => { - source.then(value => callback(value), value => callback(value)); + source.then( + value => callback(value), + value => callback(value), + ); // (Can't unsubscribe from a Promise) return () => {}; }, diff --git a/packages/eslint-plugin-react-hooks/src/ExhaustiveDeps.js b/packages/eslint-plugin-react-hooks/src/ExhaustiveDeps.js index 6e96ecddea549..9ec5e562641eb 100644 --- a/packages/eslint-plugin-react-hooks/src/ExhaustiveDeps.js +++ b/packages/eslint-plugin-react-hooks/src/ExhaustiveDeps.js @@ -613,21 +613,15 @@ export default { context.report({ node: declaredDependencyNode, message: - `The ${ - declaredDependencyNode.raw - } literal is not a valid dependency ` + + `The ${declaredDependencyNode.raw} literal is not a valid dependency ` + `because it never changes. ` + - `Did you mean to include ${ - declaredDependencyNode.value - } in the array instead?`, + `Did you mean to include ${declaredDependencyNode.value} in the array instead?`, }); } else { context.report({ node: declaredDependencyNode, message: - `The ${ - declaredDependencyNode.raw - } literal is not a valid dependency ` + + `The ${declaredDependencyNode.raw} literal is not a valid dependency ` + 'because it never changes. You can safely remove it.', }); } @@ -697,22 +691,16 @@ export default { bareFunctions.forEach(({fn, suggestUseCallback}) => { let message = `The '${fn.name.name}' function makes the dependencies of ` + - `${reactiveHookName} Hook (at line ${ - declaredDependenciesNode.loc.start.line - }) ` + + `${reactiveHookName} Hook (at line ${declaredDependenciesNode.loc.start.line}) ` + `change on every render.`; if (suggestUseCallback) { message += ` To fix this, ` + - `wrap the '${ - fn.name.name - }' definition into its own useCallback() Hook.`; + `wrap the '${fn.name.name}' definition into its own useCallback() Hook.`; } else { message += ` Move it inside the ${reactiveHookName} callback. ` + - `Alternatively, wrap the '${ - fn.name.name - }' definition into its own useCallback() Hook.`; + `Alternatively, wrap the '${fn.name.name}' definition into its own useCallback() Hook.`; } // TODO: What if the function needs to change on every render anyway? // Should we suggest removing effect deps as an appropriate fix too? diff --git a/packages/legacy-events/EventPluginUtils.js b/packages/legacy-events/EventPluginUtils.js index bdc5f237d8600..abba8e9a3dabe 100644 --- a/packages/legacy-events/EventPluginUtils.js +++ b/packages/legacy-events/EventPluginUtils.js @@ -40,15 +40,15 @@ if (__DEV__) { const listenersLen = listenersIsArr ? dispatchListeners.length : dispatchListeners - ? 1 - : 0; + ? 1 + : 0; const instancesIsArr = Array.isArray(dispatchInstances); const instancesLen = instancesIsArr ? dispatchInstances.length : dispatchInstances - ? 1 - : 0; + ? 1 + : 0; if (instancesIsArr !== listenersIsArr || instancesLen !== listenersLen) { console.error('EventPluginUtils: Invalid `event`.'); diff --git a/packages/legacy-events/ReactGenericBatching.js b/packages/legacy-events/ReactGenericBatching.js index 765e44d257cad..e5f536ee15c8f 100644 --- a/packages/legacy-events/ReactGenericBatching.js +++ b/packages/legacy-events/ReactGenericBatching.js @@ -119,7 +119,8 @@ export function flushDiscreteUpdatesIfNeeded(timeStamp: number) { if ( !isInsideEventHandler && (!enableDeprecatedFlareAPI || - (timeStamp === 0 || lastFlushedEventTimeStamp !== timeStamp)) + timeStamp === 0 || + lastFlushedEventTimeStamp !== timeStamp) ) { lastFlushedEventTimeStamp = timeStamp; flushDiscreteUpdatesImpl(); diff --git a/packages/legacy-events/ResponderEventPlugin.js b/packages/legacy-events/ResponderEventPlugin.js index ff736b8aeac0f..a5d4fe0251e53 100644 --- a/packages/legacy-events/ResponderEventPlugin.js +++ b/packages/legacy-events/ResponderEventPlugin.js @@ -350,10 +350,10 @@ function setResponderAndExtractTransfer( const shouldSetEventType = isStartish(topLevelType) ? eventTypes.startShouldSetResponder : isMoveish(topLevelType) - ? eventTypes.moveShouldSetResponder - : topLevelType === TOP_SELECTION_CHANGE - ? eventTypes.selectionChangeShouldSetResponder - : eventTypes.scrollShouldSetResponder; + ? eventTypes.moveShouldSetResponder + : topLevelType === TOP_SELECTION_CHANGE + ? eventTypes.selectionChangeShouldSetResponder + : eventTypes.scrollShouldSetResponder; // TODO: stop one short of the current responder. const bubbleShouldSetFrom = !responderInst @@ -550,10 +550,10 @@ const ResponderEventPlugin = { const incrementalTouch = isResponderTouchStart ? eventTypes.responderStart : isResponderTouchMove - ? eventTypes.responderMove - : isResponderTouchEnd - ? eventTypes.responderEnd - : null; + ? eventTypes.responderMove + : isResponderTouchEnd + ? eventTypes.responderEnd + : null; if (incrementalTouch) { const gesture = ResponderSyntheticEvent.getPooled( @@ -577,8 +577,8 @@ const ResponderEventPlugin = { const finalTouch = isResponderTerminate ? eventTypes.responderTerminate : isResponderRelease - ? eventTypes.responderRelease - : null; + ? eventTypes.responderRelease + : null; if (finalTouch) { const finalEvent = ResponderSyntheticEvent.getPooled( finalTouch, diff --git a/packages/legacy-events/__tests__/ResponderEventPlugin-test.internal.js b/packages/legacy-events/__tests__/ResponderEventPlugin-test.internal.js index abe96a3808057..a290784c95c2e 100644 --- a/packages/legacy-events/__tests__/ResponderEventPlugin-test.internal.js +++ b/packages/legacy-events/__tests__/ResponderEventPlugin-test.internal.js @@ -79,12 +79,12 @@ const _touchConfig = function( topType === 'topTouchStart' ? allTouchObjects : topType === 'topTouchMove' - ? allTouchObjects - : topType === 'topTouchEnd' - ? antiSubsequence(allTouchObjects, changedIndices) - : topType === 'topTouchCancel' - ? antiSubsequence(allTouchObjects, changedIndices) - : null; + ? allTouchObjects + : topType === 'topTouchEnd' + ? antiSubsequence(allTouchObjects, changedIndices) + : topType === 'topTouchCancel' + ? antiSubsequence(allTouchObjects, changedIndices) + : null; return { nativeEvent: touchEvent( diff --git a/packages/react-art/src/__tests__/ReactART-test.js b/packages/react-art/src/__tests__/ReactART-test.js index 1d2435436d94c..758415ef38044 100644 --- a/packages/react-art/src/__tests__/ReactART-test.js +++ b/packages/react-art/src/__tests__/ReactART-test.js @@ -214,7 +214,9 @@ describe('ReactART', () => { const chars = this.props.chars.split(''); return ( - {chars.map(text => )} + {chars.map(text => ( + + ))} ); } diff --git a/packages/react-cache/src/__tests__/ReactCache-test.internal.js b/packages/react-cache/src/__tests__/ReactCache-test.internal.js index 3a14dcfd9a9e2..0a459fc9d3a3a 100644 --- a/packages/react-cache/src/__tests__/ReactCache-test.internal.js +++ b/packages/react-cache/src/__tests__/ReactCache-test.internal.js @@ -33,46 +33,53 @@ describe('ReactCache', () => { ReactTestRenderer = require('react-test-renderer'); Scheduler = require('scheduler'); - TextResource = createResource(([text, ms = 0]) => { - let listeners = null; - let status = 'pending'; - let value = null; - return { - then(resolve, reject) { - switch (status) { - case 'pending': { - if (listeners === null) { - listeners = [{resolve, reject}]; - setTimeout(() => { - if (textResourceShouldFail) { - Scheduler.unstable_yieldValue(`Promise rejected [${text}]`); - status = 'rejected'; - value = new Error('Failed to load: ' + text); - listeners.forEach(listener => listener.reject(value)); - } else { - Scheduler.unstable_yieldValue(`Promise resolved [${text}]`); - status = 'resolved'; - value = text; - listeners.forEach(listener => listener.resolve(value)); - } - }, ms); - } else { - listeners.push({resolve, reject}); + TextResource = createResource( + ([text, ms = 0]) => { + let listeners = null; + let status = 'pending'; + let value = null; + return { + then(resolve, reject) { + switch (status) { + case 'pending': { + if (listeners === null) { + listeners = [{resolve, reject}]; + setTimeout(() => { + if (textResourceShouldFail) { + Scheduler.unstable_yieldValue( + `Promise rejected [${text}]`, + ); + status = 'rejected'; + value = new Error('Failed to load: ' + text); + listeners.forEach(listener => listener.reject(value)); + } else { + Scheduler.unstable_yieldValue( + `Promise resolved [${text}]`, + ); + status = 'resolved'; + value = text; + listeners.forEach(listener => listener.resolve(value)); + } + }, ms); + } else { + listeners.push({resolve, reject}); + } + break; + } + case 'resolved': { + resolve(value); + break; + } + case 'rejected': { + reject(value); + break; } - break; - } - case 'resolved': { - resolve(value); - break; - } - case 'rejected': { - reject(value); - break; } - } - }, - }; - }, ([text, ms]) => text); + }, + }; + }, + ([text, ms]) => text, + ); textResourceShouldFail = false; }); @@ -293,26 +300,29 @@ describe('ReactCache', () => { it('if a thenable resolves multiple times, does not update the first cached value', () => { let resolveThenable; - const BadTextResource = createResource(([text, ms = 0]) => { - let listeners = null; - let value = null; - return { - then(resolve, reject) { - if (value !== null) { - resolve(value); - } else { - if (listeners === null) { - listeners = [resolve]; - resolveThenable = v => { - listeners.forEach(listener => listener(v)); - }; + const BadTextResource = createResource( + ([text, ms = 0]) => { + let listeners = null; + let value = null; + return { + then(resolve, reject) { + if (value !== null) { + resolve(value); } else { - listeners.push(resolve); + if (listeners === null) { + listeners = [resolve]; + resolveThenable = v => { + listeners.forEach(listener => listener(v)); + }; + } else { + listeners.push(resolve); + } } - } - }, - }; - }, ([text, ms]) => text); + }, + }; + }, + ([text, ms]) => text, + ); function BadAsyncText(props) { const text = props.text; diff --git a/packages/react-debug-tools/src/ReactDebugHooks.js b/packages/react-debug-tools/src/ReactDebugHooks.js index 34c3e43b81edc..0ff4d4278b170 100644 --- a/packages/react-debug-tools/src/ReactDebugHooks.js +++ b/packages/react-debug-tools/src/ReactDebugHooks.js @@ -116,8 +116,8 @@ function useState( hook !== null ? hook.memoizedState : typeof initialState === 'function' - ? initialState() - : initialState; + ? initialState() + : initialState; hookLog.push({primitive: 'State', stackError: new Error(), value: state}); return [state, (action: BasicStateAction) => {}]; } diff --git a/packages/react-devtools-core/src/backend.js b/packages/react-devtools-core/src/backend.js index df8cb0c07ee7d..f90a68d0d2f17 100644 --- a/packages/react-devtools-core/src/backend.js +++ b/packages/react-devtools-core/src/backend.js @@ -33,9 +33,7 @@ installHook(window); const hook: DevToolsHook = window.__REACT_DEVTOOLS_GLOBAL_HOOK__; -let savedComponentFilters: Array< - ComponentFilter, -> = getDefaultComponentFilters(); +let savedComponentFilters: Array = getDefaultComponentFilters(); function debug(methodName: string, ...args) { if (__DEBUG__) { @@ -56,8 +54,7 @@ export function connectToDevTools(options: ?ConnectOptions) { websocket, resolveRNStyle = null, isAppActive = () => true, - } = - options || {}; + } = options || {}; let retryTimeoutID: TimeoutID | null = null; diff --git a/packages/react-devtools-shared/src/__tests__/inspectedElementContext-test.js b/packages/react-devtools-shared/src/__tests__/inspectedElementContext-test.js index f8691a5f39c20..82a2c5bb19306 100644 --- a/packages/react-devtools-shared/src/__tests__/inspectedElementContext-test.js +++ b/packages/react-devtools-shared/src/__tests__/inspectedElementContext-test.js @@ -520,9 +520,15 @@ describe('InspectedElementContext', () => { const exampleFunction = () => {}; const exampleDateISO = '2019-12-31T23:42:42.000Z'; const setShallow = new Set(['abc', 123]); - const mapShallow = new Map([['name', 'Brian'], ['food', 'sushi']]); + const mapShallow = new Map([ + ['name', 'Brian'], + ['food', 'sushi'], + ]); const setOfSets = new Set([new Set(['a', 'b', 'c']), new Set([1, 2, 3])]); - const mapOfMaps = new Map([['first', mapShallow], ['second', mapShallow]]); + const mapOfMaps = new Map([ + ['first', mapShallow], + ['second', mapShallow], + ]); const objectOfObjects = { inner: {string: 'abc', number: 123, boolean: true}, }; diff --git a/packages/react-devtools-shared/src/__tests__/legacy/inspectElement-test.js b/packages/react-devtools-shared/src/__tests__/legacy/inspectElement-test.js index 90b835ad235bd..8c0937ab9d3f5 100644 --- a/packages/react-devtools-shared/src/__tests__/legacy/inspectElement-test.js +++ b/packages/react-devtools-shared/src/__tests__/legacy/inspectElement-test.js @@ -151,9 +151,15 @@ describe('InspectedElementContext', () => { const div = document.createElement('div'); const exampleFunction = () => {}; const setShallow = new Set(['abc', 123]); - const mapShallow = new Map([['name', 'Brian'], ['food', 'sushi']]); + const mapShallow = new Map([ + ['name', 'Brian'], + ['food', 'sushi'], + ]); const setOfSets = new Set([new Set(['a', 'b', 'c']), new Set([1, 2, 3])]); - const mapOfMaps = new Map([['first', mapShallow], ['second', mapShallow]]); + const mapOfMaps = new Map([ + ['first', mapShallow], + ['second', mapShallow], + ]); const objectOfObjects = { inner: {string: 'abc', number: 123, boolean: true}, }; diff --git a/packages/react-devtools-shared/src/__tests__/legacy/storeLegacy-v15-test.js b/packages/react-devtools-shared/src/__tests__/legacy/storeLegacy-v15-test.js index ccc0d895806d2..fb6778521361a 100644 --- a/packages/react-devtools-shared/src/__tests__/legacy/storeLegacy-v15-test.js +++ b/packages/react-devtools-shared/src/__tests__/legacy/storeLegacy-v15-test.js @@ -63,7 +63,9 @@ describe('Store (legacy)', () => { ); const Parent = ({count}) => (

- {new Array(count).fill(true).map((_, index) => )} + {new Array(count).fill(true).map((_, index) => ( + + ))}
); const Child = () =>
Hi!
; @@ -83,7 +85,9 @@ describe('Store (legacy)', () => { it('should support mount and update operations for multiple roots', () => { const Parent = ({count}) => (
- {new Array(count).fill(true).map((_, index) => )} + {new Array(count).fill(true).map((_, index) => ( + + ))}
); const Child = () =>
Hi!
; @@ -155,7 +159,9 @@ describe('Store (legacy)', () => { ); const Parent = ({count}) => (
- {new Array(count).fill(true).map((_, index) => )} + {new Array(count).fill(true).map((_, index) => ( + + ))}
); const Child = () =>
Hi!
; @@ -261,7 +267,9 @@ describe('Store (legacy)', () => { it('should support mount and update operations', () => { const Parent = ({count}) => (
- {new Array(count).fill(true).map((_, index) => )} + {new Array(count).fill(true).map((_, index) => ( + + ))}
); const Child = () =>
Hi!
; @@ -297,7 +305,9 @@ describe('Store (legacy)', () => { it('should support mount and update operations for multiple roots', () => { const Parent = ({count}) => (
- {new Array(count).fill(true).map((_, index) => )} + {new Array(count).fill(true).map((_, index) => ( + + ))}
); const Child = () =>
Hi!
; @@ -375,7 +385,9 @@ describe('Store (legacy)', () => { ); const Parent = ({count}) => (
- {new Array(count).fill(true).map((_, index) => )} + {new Array(count).fill(true).map((_, index) => ( + + ))}
); const Child = () =>
Hi!
; diff --git a/packages/react-devtools-shared/src/backend/views/Highlighter/index.js b/packages/react-devtools-shared/src/backend/views/Highlighter/index.js index 2080ed4d78ca7..720e74e239c07 100644 --- a/packages/react-devtools-shared/src/backend/views/Highlighter/index.js +++ b/packages/react-devtools-shared/src/backend/views/Highlighter/index.js @@ -103,9 +103,9 @@ export default function setupHighlighter( let nodes: ?Array = null; if (renderer !== null) { - nodes = ((renderer.findNativeNodesForFiberID(id): any): ?Array< - HTMLElement, - >); + nodes = ((renderer.findNativeNodesForFiberID( + id, + ): any): ?Array); } if (nodes != null && nodes[0] != null) { diff --git a/packages/react-devtools-shared/src/devtools/ContextMenu/ContextMenu.js b/packages/react-devtools-shared/src/devtools/ContextMenu/ContextMenu.js index 616cd4b5869c9..891d24c0518b5 100644 --- a/packages/react-devtools-shared/src/devtools/ContextMenu/ContextMenu.js +++ b/packages/react-devtools-shared/src/devtools/ContextMenu/ContextMenu.js @@ -74,55 +74,49 @@ export default function ContextMenu({children, id}: Props) { }; }, []); - useEffect( - () => { - const showMenu = ({data, pageX, pageY}) => { - setState({data, isVisible: true, pageX, pageY}); - }; - const hideMenu = () => setState(HIDDEN_STATE); - return registerMenu(id, showMenu, hideMenu); - }, - [id], - ); - - useLayoutEffect( - () => { - if (!state.isVisible) { - return; - } + useEffect(() => { + const showMenu = ({data, pageX, pageY}) => { + setState({data, isVisible: true, pageX, pageY}); + }; + const hideMenu = () => setState(HIDDEN_STATE); + return registerMenu(id, showMenu, hideMenu); + }, [id]); - const menu = menuRef.current; + useLayoutEffect(() => { + if (!state.isVisible) { + return; + } - const hideUnlessContains = event => { - if (!menu.contains(event.target)) { - setState(HIDDEN_STATE); - } - }; + const menu = menuRef.current; - const hide = event => { + const hideUnlessContains = event => { + if (!menu.contains(event.target)) { setState(HIDDEN_STATE); - }; + } + }; - const ownerDocument = containerRef.current.ownerDocument; - ownerDocument.addEventListener('mousedown', hideUnlessContains); - ownerDocument.addEventListener('touchstart', hideUnlessContains); - ownerDocument.addEventListener('keydown', hideUnlessContains); + const hide = event => { + setState(HIDDEN_STATE); + }; - const ownerWindow = ownerDocument.defaultView; - ownerWindow.addEventListener('resize', hide); + const ownerDocument = containerRef.current.ownerDocument; + ownerDocument.addEventListener('mousedown', hideUnlessContains); + ownerDocument.addEventListener('touchstart', hideUnlessContains); + ownerDocument.addEventListener('keydown', hideUnlessContains); - respositionToFit(menu, state.pageX, state.pageY); + const ownerWindow = ownerDocument.defaultView; + ownerWindow.addEventListener('resize', hide); - return () => { - ownerDocument.removeEventListener('mousedown', hideUnlessContains); - ownerDocument.removeEventListener('touchstart', hideUnlessContains); - ownerDocument.removeEventListener('keydown', hideUnlessContains); + respositionToFit(menu, state.pageX, state.pageY); - ownerWindow.removeEventListener('resize', hide); - }; - }, - [state], - ); + return () => { + ownerDocument.removeEventListener('mousedown', hideUnlessContains); + ownerDocument.removeEventListener('touchstart', hideUnlessContains); + ownerDocument.removeEventListener('keydown', hideUnlessContains); + + ownerWindow.removeEventListener('resize', hide); + }; + }, [state]); if (!state.isVisible) { return
; diff --git a/packages/react-devtools-shared/src/devtools/ContextMenu/useContextMenu.js b/packages/react-devtools-shared/src/devtools/ContextMenu/useContextMenu.js index 1237d6c08b040..1639befc76bb9 100644 --- a/packages/react-devtools-shared/src/devtools/ContextMenu/useContextMenu.js +++ b/packages/react-devtools-shared/src/devtools/ContextMenu/useContextMenu.js @@ -23,29 +23,24 @@ export default function useContextMenu({ |}) { const {showMenu} = useContext(RegistryContext); - useEffect( - () => { - if (ref.current !== null) { - const handleContextMenu = event => { - event.preventDefault(); - event.stopPropagation(); - - const pageX = - event.pageX || (event.touches && event.touches[0].pageX); - const pageY = - event.pageY || (event.touches && event.touches[0].pageY); - - showMenu({data, id, pageX, pageY}); - }; - - const trigger = ref.current; - trigger.addEventListener('contextmenu', handleContextMenu); - - return () => { - trigger.removeEventListener('contextmenu', handleContextMenu); - }; - } - }, - [data, id, showMenu], - ); + useEffect(() => { + if (ref.current !== null) { + const handleContextMenu = event => { + event.preventDefault(); + event.stopPropagation(); + + const pageX = event.pageX || (event.touches && event.touches[0].pageX); + const pageY = event.pageY || (event.touches && event.touches[0].pageY); + + showMenu({data, id, pageX, pageY}); + }; + + const trigger = ref.current; + trigger.addEventListener('contextmenu', handleContextMenu); + + return () => { + trigger.removeEventListener('contextmenu', handleContextMenu); + }; + } + }, [data, id, showMenu]); } diff --git a/packages/react-devtools-shared/src/devtools/store.js b/packages/react-devtools-shared/src/devtools/store.js index 5cb23a4d2e877..ad46873c35e91 100644 --- a/packages/react-devtools-shared/src/devtools/store.js +++ b/packages/react-devtools-shared/src/devtools/store.js @@ -364,9 +364,7 @@ export default class Store extends EventEmitter<{| getElementAtIndex(index: number): Element | null { if (index < 0 || index >= this.numElements) { console.warn( - `Invalid index ${index} specified; store contains ${ - this.numElements - } items.`, + `Invalid index ${index} specified; store contains ${this.numElements} items.`, ); return null; diff --git a/packages/react-devtools-shared/src/devtools/utils.js b/packages/react-devtools-shared/src/devtools/utils.js index e7e8d9137c3a9..c5a07f3146fd7 100644 --- a/packages/react-devtools-shared/src/devtools/utils.js +++ b/packages/react-devtools-shared/src/devtools/utils.js @@ -90,9 +90,7 @@ export function printStore(store: Store, includeWeight: boolean = false) { // Make sure the pretty-printed test align with the Store's reported number of total rows. if (rootWeight !== store.numElements) { throw Error( - `Inconsistent Store state. Individual root weights (${rootWeight}) do not match total weight (${ - store.numElements - })`, + `Inconsistent Store state. Individual root weights (${rootWeight}) do not match total weight (${store.numElements})`, ); } diff --git a/packages/react-devtools-shared/src/devtools/views/Components/Element.js b/packages/react-devtools-shared/src/devtools/views/Components/Element.js index 56587112477a3..9f3aaed2d69b8 100644 --- a/packages/react-devtools-shared/src/devtools/views/Components/Element.js +++ b/packages/react-devtools-shared/src/devtools/views/Components/Element.js @@ -193,12 +193,9 @@ type DisplayNameProps = {| function DisplayName({displayName, id}: DisplayNameProps) { const {searchIndex, searchResults, searchText} = useContext(TreeStateContext); - const isSearchResult = useMemo( - () => { - return searchResults.includes(id); - }, - [id, searchResults], - ); + const isSearchResult = useMemo(() => { + return searchResults.includes(id); + }, [id, searchResults]); const isCurrentResult = searchIndex !== null && id === searchResults[searchIndex]; diff --git a/packages/react-devtools-shared/src/devtools/views/Components/InspectHostNodesToggle.js b/packages/react-devtools-shared/src/devtools/views/Components/InspectHostNodesToggle.js index 2bbb704e527f6..7740542881623 100644 --- a/packages/react-devtools-shared/src/devtools/views/Components/InspectHostNodesToggle.js +++ b/packages/react-devtools-shared/src/devtools/views/Components/InspectHostNodesToggle.js @@ -29,15 +29,12 @@ export default function InspectHostNodesToggle() { [bridge], ); - useEffect( - () => { - const onStopInspectingNative = () => setIsInspecting(false); - bridge.addListener('stopInspectingNative', onStopInspectingNative); - return () => - bridge.removeListener('stopInspectingNative', onStopInspectingNative); - }, - [bridge], - ); + useEffect(() => { + const onStopInspectingNative = () => setIsInspecting(false); + bridge.addListener('stopInspectingNative', onStopInspectingNative); + return () => + bridge.removeListener('stopInspectingNative', onStopInspectingNative); + }, [bridge]); return ( (null); // This effect handler invalidates the suspense cache and schedules rendering updates with React. - useEffect( - () => { - const onInspectedElement = (data: InspectedElementPayload) => { - const {id} = data; - - let element; - - switch (data.type) { - case 'no-change': - case 'not-found': - // No-op - break; - case 'hydrated-path': - // Merge new data into previous object and invalidate cache - element = store.getElementByID(id); - if (element !== null) { - if (currentlyInspectedElement != null) { - const value = hydrateHelper(data.value, data.path); - const inspectedElement = {...currentlyInspectedElement}; - - fillInPath(inspectedElement, data.value, data.path, value); - - resource.write(element, inspectedElement); - - // Schedule update with React if the curently-selected element has been invalidated. - if (id === selectedElementID) { - setCurrentlyInspectedElement(inspectedElement); - } + useEffect(() => { + const onInspectedElement = (data: InspectedElementPayload) => { + const {id} = data; + + let element; + + switch (data.type) { + case 'no-change': + case 'not-found': + // No-op + break; + case 'hydrated-path': + // Merge new data into previous object and invalidate cache + element = store.getElementByID(id); + if (element !== null) { + if (currentlyInspectedElement != null) { + const value = hydrateHelper(data.value, data.path); + const inspectedElement = {...currentlyInspectedElement}; + + fillInPath(inspectedElement, data.value, data.path, value); + + resource.write(element, inspectedElement); + + // Schedule update with React if the curently-selected element has been invalidated. + if (id === selectedElementID) { + setCurrentlyInspectedElement(inspectedElement); } } - break; - case 'full-data': - const { - canEditFunctionProps, - canEditHooks, - canToggleSuspense, - canViewSource, - hasLegacyContext, - source, - type, - owners, - context, - hooks, - props, - state, - } = ((data.value: any): InspectedElementBackend); - - const inspectedElement: InspectedElementFrontend = { - canEditFunctionProps, - canEditHooks, - canToggleSuspense, - canViewSource, - hasLegacyContext, - id, - source, - type, - owners: - owners === null - ? null - : owners.map(owner => { - const [ - displayName, - hocDisplayNames, - ] = separateDisplayNameAndHOCs( - owner.displayName, - owner.type, - ); - return { - ...owner, - displayName, - hocDisplayNames, - }; - }), - context: hydrateHelper(context), - hooks: hydrateHelper(hooks), - props: hydrateHelper(props), - state: hydrateHelper(state), - }; - - element = store.getElementByID(id); - if (element !== null) { - const request = inProgressRequests.get(element); - if (request != null) { - inProgressRequests.delete(element); - batchedUpdates(() => { - request.resolveFn(inspectedElement); - setCurrentlyInspectedElement(inspectedElement); - }); - } else { - resource.write(element, inspectedElement); - - // Schedule update with React if the curently-selected element has been invalidated. - if (id === selectedElementID) { - setCurrentlyInspectedElement(inspectedElement); - } + } + break; + case 'full-data': + const { + canEditFunctionProps, + canEditHooks, + canToggleSuspense, + canViewSource, + hasLegacyContext, + source, + type, + owners, + context, + hooks, + props, + state, + } = ((data.value: any): InspectedElementBackend); + + const inspectedElement: InspectedElementFrontend = { + canEditFunctionProps, + canEditHooks, + canToggleSuspense, + canViewSource, + hasLegacyContext, + id, + source, + type, + owners: + owners === null + ? null + : owners.map(owner => { + const [ + displayName, + hocDisplayNames, + ] = separateDisplayNameAndHOCs( + owner.displayName, + owner.type, + ); + return { + ...owner, + displayName, + hocDisplayNames, + }; + }), + context: hydrateHelper(context), + hooks: hydrateHelper(hooks), + props: hydrateHelper(props), + state: hydrateHelper(state), + }; + + element = store.getElementByID(id); + if (element !== null) { + const request = inProgressRequests.get(element); + if (request != null) { + inProgressRequests.delete(element); + batchedUpdates(() => { + request.resolveFn(inspectedElement); + setCurrentlyInspectedElement(inspectedElement); + }); + } else { + resource.write(element, inspectedElement); + + // Schedule update with React if the curently-selected element has been invalidated. + if (id === selectedElementID) { + setCurrentlyInspectedElement(inspectedElement); } } - break; - default: - break; - } - }; + } + break; + default: + break; + } + }; - bridge.addListener('inspectedElement', onInspectedElement); - return () => - bridge.removeListener('inspectedElement', onInspectedElement); - }, - [bridge, currentlyInspectedElement, selectedElementID, store], - ); + bridge.addListener('inspectedElement', onInspectedElement); + return () => bridge.removeListener('inspectedElement', onInspectedElement); + }, [bridge, currentlyInspectedElement, selectedElementID, store]); // This effect handler polls for updates on the currently selected element. - useEffect( - () => { - if (selectedElementID === null) { - return () => {}; - } + useEffect(() => { + if (selectedElementID === null) { + return () => {}; + } - const rendererID = store.getRendererIDForElement(selectedElementID); + const rendererID = store.getRendererIDForElement(selectedElementID); - let timeoutID: TimeoutID | null = null; + let timeoutID: TimeoutID | null = null; - const sendRequest = () => { - timeoutID = null; + const sendRequest = () => { + timeoutID = null; - if (rendererID !== null) { - bridge.send('inspectElement', {id: selectedElementID, rendererID}); - } - }; - - // Send the initial inspection request. - // We'll poll for an update in the response handler below. - sendRequest(); - - const onInspectedElement = (data: InspectedElementPayload) => { - // If this is the element we requested, wait a little bit and then ask for another update. - if (data.id === selectedElementID) { - switch (data.type) { - case 'no-change': - case 'full-data': - case 'hydrated-path': - if (timeoutID !== null) { - clearTimeout(timeoutID); - } - timeoutID = setTimeout(sendRequest, 1000); - break; - default: - break; - } + if (rendererID !== null) { + bridge.send('inspectElement', {id: selectedElementID, rendererID}); + } + }; + + // Send the initial inspection request. + // We'll poll for an update in the response handler below. + sendRequest(); + + const onInspectedElement = (data: InspectedElementPayload) => { + // If this is the element we requested, wait a little bit and then ask for another update. + if (data.id === selectedElementID) { + switch (data.type) { + case 'no-change': + case 'full-data': + case 'hydrated-path': + if (timeoutID !== null) { + clearTimeout(timeoutID); + } + timeoutID = setTimeout(sendRequest, 1000); + break; + default: + break; } - }; + } + }; - bridge.addListener('inspectedElement', onInspectedElement); + bridge.addListener('inspectedElement', onInspectedElement); - return () => { - bridge.removeListener('inspectedElement', onInspectedElement); + return () => { + bridge.removeListener('inspectedElement', onInspectedElement); - if (timeoutID !== null) { - clearTimeout(timeoutID); - } - }; - }, - [bridge, selectedElementID, store], - ); + if (timeoutID !== null) { + clearTimeout(timeoutID); + } + }; + }, [bridge, selectedElementID, store]); const value = useMemo( () => ({ diff --git a/packages/react-devtools-shared/src/devtools/views/Components/KeyValue.js b/packages/react-devtools-shared/src/devtools/views/Components/KeyValue.js index f199078005033..e45a5488c4a7a 100644 --- a/packages/react-devtools-shared/src/devtools/views/Components/KeyValue.js +++ b/packages/react-devtools-shared/src/devtools/views/Components/KeyValue.js @@ -55,20 +55,17 @@ export default function KeyValue({ value[meta.inspectable] && value[meta.size] !== 0; - useEffect( - () => { - if ( - isInspectable && - isOpen && - !prevIsOpenRef.current && - typeof inspectPath === 'function' - ) { - inspectPath(path); - } - prevIsOpenRef.current = isOpen; - }, - [inspectPath, isInspectable, isOpen, path], - ); + useEffect(() => { + if ( + isInspectable && + isOpen && + !prevIsOpenRef.current && + typeof inspectPath === 'function' + ) { + inspectPath(path); + } + prevIsOpenRef.current = isOpen; + }, [inspectPath, isInspectable, isOpen, path]); const toggleIsOpen = () => setIsOpen(prevIsOpen => !prevIsOpen); diff --git a/packages/react-devtools-shared/src/devtools/views/Components/NativeStyleEditor/AutoSizeInput.js b/packages/react-devtools-shared/src/devtools/views/Components/NativeStyleEditor/AutoSizeInput.js index 4adcae74fb902..03d6b47b51948 100644 --- a/packages/react-devtools-shared/src/devtools/views/Components/NativeStyleEditor/AutoSizeInput.js +++ b/packages/react-devtools-shared/src/devtools/views/Components/NativeStyleEditor/AutoSizeInput.js @@ -65,27 +65,24 @@ export default function AutoSizeInput({ }, []); // Resize input any time text changes - useLayoutEffect( - () => { - if (hiddenDivRef.current === null) { - return; - } + useLayoutEffect(() => { + if (hiddenDivRef.current === null) { + return; + } - const scrollWidth = hiddenDivRef.current.getBoundingClientRect().width; - if (!scrollWidth) { - return; - } + const scrollWidth = hiddenDivRef.current.getBoundingClientRect().width; + if (!scrollWidth) { + return; + } - // Adding an extra pixel avoids a slight horizontal scroll when changing text selection/cursor. - // Not sure why this is, but the old DevTools did a similar thing. - const targetWidth = Math.ceil(scrollWidth) + 1; + // Adding an extra pixel avoids a slight horizontal scroll when changing text selection/cursor. + // Not sure why this is, but the old DevTools did a similar thing. + const targetWidth = Math.ceil(scrollWidth) + 1; - if (inputRef.current !== null) { - inputRef.current.style.width = `${targetWidth}px`; - } - }, - [value], - ); + if (inputRef.current !== null) { + inputRef.current.style.width = `${targetWidth}px`; + } + }, [value]); const isEmpty = value === '' || value === '""'; diff --git a/packages/react-devtools-shared/src/devtools/views/Components/NativeStyleEditor/context.js b/packages/react-devtools-shared/src/devtools/views/Components/NativeStyleEditor/context.js index 52b1a285dda68..2542957f882fb 100644 --- a/packages/react-devtools-shared/src/devtools/views/Components/NativeStyleEditor/context.js +++ b/packages/react-devtools-shared/src/devtools/views/Components/NativeStyleEditor/context.js @@ -102,94 +102,88 @@ function NativeStyleContextController({children}: Props) { ] = useState(null); // This effect handler invalidates the suspense cache and schedules rendering updates with React. - useEffect( - () => { - const onStyleAndLayout = ({id, layout, style}: StyleAndLayoutBackend) => { - let element = store.getElementByID(id); - if (element !== null) { - const styleAndLayout: StyleAndLayoutFrontend = { - layout, - style, - }; - const request = inProgressRequests.get(element); - if (request != null) { - inProgressRequests.delete(element); - batchedUpdates(() => { - request.resolveFn(styleAndLayout); - setCurrentStyleAndLayout(styleAndLayout); - }); - } else { - resource.write(element, styleAndLayout); - - // Schedule update with React if the currently-selected element has been invalidated. - if (id === selectedElementID) { - setCurrentStyleAndLayout(styleAndLayout); - } + useEffect(() => { + const onStyleAndLayout = ({id, layout, style}: StyleAndLayoutBackend) => { + let element = store.getElementByID(id); + if (element !== null) { + const styleAndLayout: StyleAndLayoutFrontend = { + layout, + style, + }; + const request = inProgressRequests.get(element); + if (request != null) { + inProgressRequests.delete(element); + batchedUpdates(() => { + request.resolveFn(styleAndLayout); + setCurrentStyleAndLayout(styleAndLayout); + }); + } else { + resource.write(element, styleAndLayout); + + // Schedule update with React if the currently-selected element has been invalidated. + if (id === selectedElementID) { + setCurrentStyleAndLayout(styleAndLayout); } } - }; - - bridge.addListener('NativeStyleEditor_styleAndLayout', onStyleAndLayout); - return () => - bridge.removeListener( - 'NativeStyleEditor_styleAndLayout', - onStyleAndLayout, - ); - }, - [bridge, currentStyleAndLayout, selectedElementID, store], - ); - - // This effect handler polls for updates on the currently selected element. - useEffect( - () => { - if (selectedElementID === null) { - return () => {}; } + }; - const rendererID = store.getRendererIDForElement(selectedElementID); - - let timeoutID: TimeoutID | null = null; + bridge.addListener('NativeStyleEditor_styleAndLayout', onStyleAndLayout); + return () => + bridge.removeListener( + 'NativeStyleEditor_styleAndLayout', + onStyleAndLayout, + ); + }, [bridge, currentStyleAndLayout, selectedElementID, store]); - const sendRequest = () => { - timeoutID = null; + // This effect handler polls for updates on the currently selected element. + useEffect(() => { + if (selectedElementID === null) { + return () => {}; + } - if (rendererID !== null) { - bridge.send('NativeStyleEditor_measure', { - id: selectedElementID, - rendererID, - }); - } - }; + const rendererID = store.getRendererIDForElement(selectedElementID); - // Send the initial measurement request. - // We'll poll for an update in the response handler below. - sendRequest(); + let timeoutID: TimeoutID | null = null; - const onStyleAndLayout = ({id}: StyleAndLayoutBackend) => { - // If this is the element we requested, wait a little bit and then ask for another update. - if (id === selectedElementID) { - if (timeoutID !== null) { - clearTimeout(timeoutID); - } - timeoutID = setTimeout(sendRequest, 1000); - } - }; + const sendRequest = () => { + timeoutID = null; - bridge.addListener('NativeStyleEditor_styleAndLayout', onStyleAndLayout); + if (rendererID !== null) { + bridge.send('NativeStyleEditor_measure', { + id: selectedElementID, + rendererID, + }); + } + }; - return () => { - bridge.removeListener( - 'NativeStyleEditor_styleAndLayout', - onStyleAndLayout, - ); + // Send the initial measurement request. + // We'll poll for an update in the response handler below. + sendRequest(); + const onStyleAndLayout = ({id}: StyleAndLayoutBackend) => { + // If this is the element we requested, wait a little bit and then ask for another update. + if (id === selectedElementID) { if (timeoutID !== null) { clearTimeout(timeoutID); } - }; - }, - [bridge, selectedElementID, store], - ); + timeoutID = setTimeout(sendRequest, 1000); + } + }; + + bridge.addListener('NativeStyleEditor_styleAndLayout', onStyleAndLayout); + + return () => { + bridge.removeListener( + 'NativeStyleEditor_styleAndLayout', + onStyleAndLayout, + ); + + if (timeoutID !== null) { + clearTimeout(timeoutID); + } + }; + }, [bridge, selectedElementID, store]); const value = useMemo( () => ({getStyleAndLayout}), diff --git a/packages/react-devtools-shared/src/devtools/views/Components/OwnersListContext.js b/packages/react-devtools-shared/src/devtools/views/Components/OwnersListContext.js index c1faab02da1ef..aae74b4f84b50 100644 --- a/packages/react-devtools-shared/src/devtools/views/Components/OwnersListContext.js +++ b/packages/react-devtools-shared/src/devtools/views/Components/OwnersListContext.js @@ -73,60 +73,51 @@ function OwnersListContextController({children}: Props) { [store], ); - useEffect( - () => { - const onOwnersList = (ownersList: OwnersList) => { - const id = ownersList.id; - - const element = store.getElementByID(id); - if (element !== null) { - const request = inProgressRequests.get(element); - if (request != null) { - inProgressRequests.delete(element); - - request.resolveFn( - ownersList.owners === null - ? null - : ownersList.owners.map(owner => { - const [ - displayNameWithoutHOCs, - hocDisplayNames, - ] = separateDisplayNameAndHOCs( - owner.displayName, - owner.type, - ); - - return { - ...owner, - displayName: displayNameWithoutHOCs, - hocDisplayNames, - }; - }), - ); - } + useEffect(() => { + const onOwnersList = (ownersList: OwnersList) => { + const id = ownersList.id; + + const element = store.getElementByID(id); + if (element !== null) { + const request = inProgressRequests.get(element); + if (request != null) { + inProgressRequests.delete(element); + + request.resolveFn( + ownersList.owners === null + ? null + : ownersList.owners.map(owner => { + const [ + displayNameWithoutHOCs, + hocDisplayNames, + ] = separateDisplayNameAndHOCs(owner.displayName, owner.type); + + return { + ...owner, + displayName: displayNameWithoutHOCs, + hocDisplayNames, + }; + }), + ); } - }; + } + }; - bridge.addListener('ownersList', onOwnersList); - return () => bridge.removeListener('ownersList', onOwnersList); - }, - [bridge, store], - ); + bridge.addListener('ownersList', onOwnersList); + return () => bridge.removeListener('ownersList', onOwnersList); + }, [bridge, store]); // This effect requests an updated owners list any time the selected owner changes - useEffect( - () => { - if (ownerID !== null) { - const rendererID = store.getRendererIDForElement(ownerID); - if (rendererID !== null) { - bridge.send('getOwnersList', {id: ownerID, rendererID}); - } + useEffect(() => { + if (ownerID !== null) { + const rendererID = store.getRendererIDForElement(ownerID); + if (rendererID !== null) { + bridge.send('getOwnersList', {id: ownerID, rendererID}); } + } - return () => {}; - }, - [bridge, ownerID, store], - ); + return () => {}; + }, [bridge, ownerID, store]); return ( diff --git a/packages/react-devtools-shared/src/devtools/views/Components/OwnersStack.js b/packages/react-devtools-shared/src/devtools/views/Components/OwnersStack.js index 669a12e349d34..fa627299fb80e 100644 --- a/packages/react-devtools-shared/src/devtools/views/Components/OwnersStack.js +++ b/packages/react-devtools-shared/src/devtools/views/Components/OwnersStack.js @@ -128,30 +128,27 @@ export default function OwnerStack() { const selectedOwner = owners[selectedIndex]; - useLayoutEffect( - () => { - // If we're already overflowing, then we don't need to re-measure items. - // That's because once the owners stack is open, it can only get larger (by driling in). - // A totally new stack can only be reached by exiting this mode and re-entering it. - if (elementsBarRef.current === null || isOverflowing) { - return () => {}; - } - - let totalWidth = 0; - for (let i = 0; i < owners.length; i++) { - const element = elementsBarRef.current.children[i]; - const computedStyle = getComputedStyle(element); - - totalWidth += - element.offsetWidth + - parseInt(computedStyle.marginLeft, 10) + - parseInt(computedStyle.marginRight, 10); - } - - setElementsTotalWidth(totalWidth); - }, - [elementsBarRef, isOverflowing, owners.length], - ); + useLayoutEffect(() => { + // If we're already overflowing, then we don't need to re-measure items. + // That's because once the owners stack is open, it can only get larger (by driling in). + // A totally new stack can only be reached by exiting this mode and re-entering it. + if (elementsBarRef.current === null || isOverflowing) { + return () => {}; + } + + let totalWidth = 0; + for (let i = 0; i < owners.length; i++) { + const element = elementsBarRef.current.children[i]; + const computedStyle = getComputedStyle(element); + + totalWidth += + element.offsetWidth + + parseInt(computedStyle.marginLeft, 10) + + parseInt(computedStyle.marginRight, 10); + } + + setElementsTotalWidth(totalWidth); + }, [elementsBarRef, isOverflowing, owners.length]); return (
@@ -255,14 +252,11 @@ function ElementView({isSelected, owner, selectOwner}: ElementViewProps) { const {displayName, hocDisplayNames, type} = owner; const isInStore = store.containsElement(owner.id); - const handleChange = useCallback( - () => { - if (isInStore) { - selectOwner(owner); - } - }, - [isInStore, selectOwner, owner], - ); + const handleChange = useCallback(() => { + if (isInStore) { + selectOwner(owner); + } + }, [isInStore, selectOwner, owner]); return ( { - if (inputRef.current === null) { - return () => {}; - } + useEffect(() => { + if (inputRef.current === null) { + return () => {}; + } - const handleWindowKey = (event: KeyboardEvent) => { - const {key, metaKey} = event; - if (key === 'f' && metaKey) { - if (inputRef.current !== null) { - inputRef.current.focus(); - event.preventDefault(); - event.stopPropagation(); - } + const handleWindowKey = (event: KeyboardEvent) => { + const {key, metaKey} = event; + if (key === 'f' && metaKey) { + if (inputRef.current !== null) { + inputRef.current.focus(); + event.preventDefault(); + event.stopPropagation(); } - }; + } + }; - // It's important to listen to the ownerDocument to support the browser extension. - // Here we use portals to render individual tabs (e.g. Profiler), - // and the root document might belong to a different window. - const ownerDocument = inputRef.current.ownerDocument; - ownerDocument.addEventListener('keydown', handleWindowKey); + // It's important to listen to the ownerDocument to support the browser extension. + // Here we use portals to render individual tabs (e.g. Profiler), + // and the root document might belong to a different window. + const ownerDocument = inputRef.current.ownerDocument; + ownerDocument.addEventListener('keydown', handleWindowKey); - return () => - ownerDocument.removeEventListener('keydown', handleWindowKey); - }, - [inputRef], - ); + return () => ownerDocument.removeEventListener('keydown', handleWindowKey); + }, [inputRef]); return (
diff --git a/packages/react-devtools-shared/src/devtools/views/Components/SelectedElement.js b/packages/react-devtools-shared/src/devtools/views/Components/SelectedElement.js index 055378efca79f..432f5a5436126 100644 --- a/packages/react-devtools-shared/src/devtools/views/Components/SelectedElement.js +++ b/packages/react-devtools-shared/src/devtools/views/Components/SelectedElement.js @@ -72,51 +72,42 @@ export default function SelectedElement(_: Props) { const inspectedElement = inspectedElementID != null ? getInspectedElement(inspectedElementID) : null; - const highlightElement = useCallback( - () => { - if (element !== null && inspectedElementID !== null) { - const rendererID = store.getRendererIDForElement(inspectedElementID); - if (rendererID !== null) { - bridge.send('highlightNativeElement', { - displayName: element.displayName, - hideAfterTimeout: true, - id: inspectedElementID, - openNativeElementsPanel: true, - rendererID, - scrollIntoView: true, - }); - } - } - }, - [bridge, element, inspectedElementID, store], - ); - - const logElement = useCallback( - () => { - if (inspectedElementID !== null) { - const rendererID = store.getRendererIDForElement(inspectedElementID); - if (rendererID !== null) { - bridge.send('logElementToConsole', { - id: inspectedElementID, - rendererID, - }); - } + const highlightElement = useCallback(() => { + if (element !== null && inspectedElementID !== null) { + const rendererID = store.getRendererIDForElement(inspectedElementID); + if (rendererID !== null) { + bridge.send('highlightNativeElement', { + displayName: element.displayName, + hideAfterTimeout: true, + id: inspectedElementID, + openNativeElementsPanel: true, + rendererID, + scrollIntoView: true, + }); } - }, - [bridge, inspectedElementID, store], - ); + } + }, [bridge, element, inspectedElementID, store]); - const viewSource = useCallback( - () => { - if (viewElementSourceFunction != null && inspectedElement !== null) { - viewElementSourceFunction( - inspectedElement.id, - ((inspectedElement: any): InspectedElement), - ); + const logElement = useCallback(() => { + if (inspectedElementID !== null) { + const rendererID = store.getRendererIDForElement(inspectedElementID); + if (rendererID !== null) { + bridge.send('logElementToConsole', { + id: inspectedElementID, + rendererID, + }); } - }, - [inspectedElement, viewElementSourceFunction], - ); + } + }, [bridge, inspectedElementID, store]); + + const viewSource = useCallback(() => { + if (viewElementSourceFunction != null && inspectedElement !== null) { + viewElementSourceFunction( + inspectedElement.id, + ((inspectedElement: any): InspectedElement), + ); + } + }, [inspectedElement, viewElementSourceFunction]); // In some cases (e.g. FB internal usage) the standalone shell might not be able to view the source. // To detect this case, we defer to an injected helper function (if present). @@ -137,56 +128,53 @@ export default function SelectedElement(_: Props) { inspectedElement != null && inspectedElement.canToggleSuspense; // TODO (suspense toggle) Would be nice to eventually use a two setState pattern here as well. - const toggleSuspended = useCallback( - () => { - let nearestSuspenseElement = null; - let currentElement = element; - while (currentElement !== null) { - if (currentElement.type === ElementTypeSuspense) { - nearestSuspenseElement = currentElement; - break; - } else if (currentElement.parentID > 0) { - currentElement = store.getElementByID(currentElement.parentID); - } else { - currentElement = null; - } + const toggleSuspended = useCallback(() => { + let nearestSuspenseElement = null; + let currentElement = element; + while (currentElement !== null) { + if (currentElement.type === ElementTypeSuspense) { + nearestSuspenseElement = currentElement; + break; + } else if (currentElement.parentID > 0) { + currentElement = store.getElementByID(currentElement.parentID); + } else { + currentElement = null; } + } - // If we didn't find a Suspense ancestor, we can't suspend. - // Instead we can show a warning to the user. - if (nearestSuspenseElement === null) { - modalDialogDispatch({ - type: 'SHOW', - content: , + // If we didn't find a Suspense ancestor, we can't suspend. + // Instead we can show a warning to the user. + if (nearestSuspenseElement === null) { + modalDialogDispatch({ + type: 'SHOW', + content: , + }); + } else { + const nearestSuspenseElementID = nearestSuspenseElement.id; + + // If we're suspending from an arbitary (non-Suspense) component, select the nearest Suspense element in the Tree. + // This way when the fallback UI is shown and the current element is hidden, something meaningful is selected. + if (nearestSuspenseElement !== element) { + dispatch({ + type: 'SELECT_ELEMENT_BY_ID', + payload: nearestSuspenseElementID, }); - } else { - const nearestSuspenseElementID = nearestSuspenseElement.id; - - // If we're suspending from an arbitary (non-Suspense) component, select the nearest Suspense element in the Tree. - // This way when the fallback UI is shown and the current element is hidden, something meaningful is selected. - if (nearestSuspenseElement !== element) { - dispatch({ - type: 'SELECT_ELEMENT_BY_ID', - payload: nearestSuspenseElementID, - }); - } - - const rendererID = store.getRendererIDForElement( - nearestSuspenseElementID, - ); - - // Toggle suspended - if (rendererID !== null) { - bridge.send('overrideSuspense', { - id: nearestSuspenseElementID, - rendererID, - forceFallback: !isSuspended, - }); - } } - }, - [bridge, dispatch, element, isSuspended, modalDialogDispatch, store], - ); + + const rendererID = store.getRendererIDForElement( + nearestSuspenseElementID, + ); + + // Toggle suspended + if (rendererID !== null) { + bridge.send('overrideSuspense', { + id: nearestSuspenseElementID, + rendererID, + forceFallback: !isSuspended, + }); + } + } + }, [bridge, dispatch, element, isSuspended, modalDialogDispatch, store]); if (element === null) { return ( @@ -417,23 +405,21 @@ function InspectedElementView({ - {ownerID === null && - owners !== null && - owners.length > 0 && ( -
-
rendered by
- {owners.map(owner => ( - - ))} -
- )} + {ownerID === null && owners !== null && owners.length > 0 && ( +
+
rendered by
+ {owners.map(owner => ( + + ))} +
+ )} {source !== null && ( diff --git a/packages/react-devtools-shared/src/devtools/views/Components/Tree.js b/packages/react-devtools-shared/src/devtools/views/Components/Tree.js index 2c65df8fa1999..fe03d443ffac6 100644 --- a/packages/react-devtools-shared/src/devtools/views/Components/Tree.js +++ b/packages/react-devtools-shared/src/devtools/views/Components/Tree.js @@ -89,22 +89,16 @@ export default function Tree(props: Props) { // Picking an element in the inspector should put focus into the tree. // This ensures that keyboard navigation works right after picking a node. - useEffect( - () => { - function handleStopInspectingNative(didSelectNode) { - if (didSelectNode && focusTargetRef.current !== null) { - focusTargetRef.current.focus(); - } + useEffect(() => { + function handleStopInspectingNative(didSelectNode) { + if (didSelectNode && focusTargetRef.current !== null) { + focusTargetRef.current.focus(); } - bridge.addListener('stopInspectingNative', handleStopInspectingNative); - return () => - bridge.removeListener( - 'stopInspectingNative', - handleStopInspectingNative, - ); - }, - [bridge], - ); + } + bridge.addListener('stopInspectingNative', handleStopInspectingNative); + return () => + bridge.removeListener('stopInspectingNative', handleStopInspectingNative); + }, [bridge]); // This ref is passed down the context to elements. // It lets them avoid autoscrolling to the same item many times @@ -112,93 +106,87 @@ export default function Tree(props: Props) { const lastScrolledIDRef = useRef(null); // Navigate the tree with up/down arrow keys. - useEffect( - () => { - if (treeRef.current === null) { - return () => {}; + useEffect(() => { + if (treeRef.current === null) { + return () => {}; + } + + const handleKeyDown = (event: KeyboardEvent) => { + if ((event: any).target.tagName === 'INPUT' || event.defaultPrevented) { + return; } - const handleKeyDown = (event: KeyboardEvent) => { - if ((event: any).target.tagName === 'INPUT' || event.defaultPrevented) { - return; - } - - // TODO We should ignore arrow keys if the focus is outside of DevTools. - // Otherwise the inline (embedded) DevTools might change selection unexpectedly, - // e.g. when a text input or a select has focus. - - let element; - switch (event.key) { - case 'ArrowDown': - event.preventDefault(); - dispatch({type: 'SELECT_NEXT_ELEMENT_IN_TREE'}); - break; - case 'ArrowLeft': - event.preventDefault(); - element = - selectedElementID !== null - ? store.getElementByID(selectedElementID) - : null; - if (element !== null) { - if (element.children.length > 0 && !element.isCollapsed) { - store.toggleIsCollapsed(element.id, true); - } else { - dispatch({type: 'SELECT_PARENT_ELEMENT_IN_TREE'}); - } + // TODO We should ignore arrow keys if the focus is outside of DevTools. + // Otherwise the inline (embedded) DevTools might change selection unexpectedly, + // e.g. when a text input or a select has focus. + + let element; + switch (event.key) { + case 'ArrowDown': + event.preventDefault(); + dispatch({type: 'SELECT_NEXT_ELEMENT_IN_TREE'}); + break; + case 'ArrowLeft': + event.preventDefault(); + element = + selectedElementID !== null + ? store.getElementByID(selectedElementID) + : null; + if (element !== null) { + if (element.children.length > 0 && !element.isCollapsed) { + store.toggleIsCollapsed(element.id, true); + } else { + dispatch({type: 'SELECT_PARENT_ELEMENT_IN_TREE'}); } - break; - case 'ArrowRight': - event.preventDefault(); - element = - selectedElementID !== null - ? store.getElementByID(selectedElementID) - : null; - if (element !== null) { - if (element.children.length > 0 && element.isCollapsed) { - store.toggleIsCollapsed(element.id, false); - } else { - dispatch({type: 'SELECT_CHILD_ELEMENT_IN_TREE'}); - } + } + break; + case 'ArrowRight': + event.preventDefault(); + element = + selectedElementID !== null + ? store.getElementByID(selectedElementID) + : null; + if (element !== null) { + if (element.children.length > 0 && element.isCollapsed) { + store.toggleIsCollapsed(element.id, false); + } else { + dispatch({type: 'SELECT_CHILD_ELEMENT_IN_TREE'}); } - break; - case 'ArrowUp': - event.preventDefault(); - dispatch({type: 'SELECT_PREVIOUS_ELEMENT_IN_TREE'}); - break; - default: - return; - } - setIsNavigatingWithKeyboard(true); - }; - - // It's important to listen to the ownerDocument to support the browser extension. - // Here we use portals to render individual tabs (e.g. Profiler), - // and the root document might belong to a different window. - const ownerDocument = treeRef.current.ownerDocument; - ownerDocument.addEventListener('keydown', handleKeyDown); - - return () => { - ownerDocument.removeEventListener('keydown', handleKeyDown); - }; - }, - [dispatch, selectedElementID, store], - ); + } + break; + case 'ArrowUp': + event.preventDefault(); + dispatch({type: 'SELECT_PREVIOUS_ELEMENT_IN_TREE'}); + break; + default: + return; + } + setIsNavigatingWithKeyboard(true); + }; + + // It's important to listen to the ownerDocument to support the browser extension. + // Here we use portals to render individual tabs (e.g. Profiler), + // and the root document might belong to a different window. + const ownerDocument = treeRef.current.ownerDocument; + ownerDocument.addEventListener('keydown', handleKeyDown); + + return () => { + ownerDocument.removeEventListener('keydown', handleKeyDown); + }; + }, [dispatch, selectedElementID, store]); // Focus management. const handleBlur = useCallback(() => setTreeFocused(false), []); - const handleFocus = useCallback( - () => { - setTreeFocused(true); - - if (selectedElementIndex === null && numElements > 0) { - dispatch({ - type: 'SELECT_ELEMENT_AT_INDEX', - payload: 0, - }); - } - }, - [dispatch, numElements, selectedElementIndex], - ); + const handleFocus = useCallback(() => { + setTreeFocused(true); + + if (selectedElementIndex === null && numElements > 0) { + dispatch({ + type: 'SELECT_ELEMENT_AT_INDEX', + payload: 0, + }); + } + }, [dispatch, numElements, selectedElementIndex]); const handleKeyPress = useCallback( event => { @@ -237,34 +225,31 @@ export default function Tree(props: Props) { // If we switch the selected element while using the keyboard, // start highlighting it in the DOM instead of the last hovered node. const searchRef = useRef({searchIndex, searchResults}); - useEffect( - () => { - let didSelectNewSearchResult = false; - if ( - searchRef.current.searchIndex !== searchIndex || - searchRef.current.searchResults !== searchResults - ) { - searchRef.current.searchIndex = searchIndex; - searchRef.current.searchResults = searchResults; - didSelectNewSearchResult = true; - } - if (isNavigatingWithKeyboard || didSelectNewSearchResult) { - if (selectedElementID !== null) { - highlightNativeElement(selectedElementID); - } else { - bridge.send('clearNativeElementHighlight'); - } + useEffect(() => { + let didSelectNewSearchResult = false; + if ( + searchRef.current.searchIndex !== searchIndex || + searchRef.current.searchResults !== searchResults + ) { + searchRef.current.searchIndex = searchIndex; + searchRef.current.searchResults = searchResults; + didSelectNewSearchResult = true; + } + if (isNavigatingWithKeyboard || didSelectNewSearchResult) { + if (selectedElementID !== null) { + highlightNativeElement(selectedElementID); + } else { + bridge.send('clearNativeElementHighlight'); } - }, - [ - bridge, - isNavigatingWithKeyboard, - highlightNativeElement, - searchIndex, - searchResults, - selectedElementID, - ], - ); + } + }, [ + bridge, + isNavigatingWithKeyboard, + highlightNativeElement, + searchIndex, + searchResults, + selectedElementID, + ]); // Highlight last hovered element. const handleElementMouseEnter = useCallback( @@ -284,12 +269,9 @@ export default function Tree(props: Props) { setIsNavigatingWithKeyboard(false); }, []); - const handleMouseLeave = useCallback( - () => { - bridge.send('clearNativeElementHighlight'); - }, - [bridge], - ); + const handleMouseLeave = useCallback(() => { + bridge.send('clearNativeElementHighlight'); + }, [bridge]); // Let react-window know to re-render any time the underlying tree data changes. // This includes the owner context, since it controls a filtered view of the tree. diff --git a/packages/react-devtools-shared/src/devtools/views/Components/TreeContext.js b/packages/react-devtools-shared/src/devtools/views/Components/TreeContext.js index 54738bf3d4b71..bdd1fc04cfe54 100644 --- a/packages/react-devtools-shared/src/devtools/views/Components/TreeContext.js +++ b/packages/react-devtools-shared/src/devtools/views/Components/TreeContext.js @@ -718,65 +718,56 @@ function TreeContextController({ ); // Listen for host element selections. - useEffect( - () => { - const handleSelectFiber = (id: number) => - dispatchWrapper({type: 'SELECT_ELEMENT_BY_ID', payload: id}); - bridge.addListener('selectFiber', handleSelectFiber); - return () => bridge.removeListener('selectFiber', handleSelectFiber); - }, - [bridge, dispatchWrapper], - ); + useEffect(() => { + const handleSelectFiber = (id: number) => + dispatchWrapper({type: 'SELECT_ELEMENT_BY_ID', payload: id}); + bridge.addListener('selectFiber', handleSelectFiber); + return () => bridge.removeListener('selectFiber', handleSelectFiber); + }, [bridge, dispatchWrapper]); // If a newly-selected search result or inspection selection is inside of a collapsed subtree, auto expand it. // This needs to be a layout effect to avoid temporarily flashing an incorrect selection. const prevSelectedElementID = useRef(null); - useLayoutEffect( - () => { - if (state.selectedElementID !== prevSelectedElementID.current) { - prevSelectedElementID.current = state.selectedElementID; - - if (state.selectedElementID !== null) { - let element = store.getElementByID(state.selectedElementID); - if (element !== null && element.parentID > 0) { - store.toggleIsCollapsed(element.parentID, false); - } + useLayoutEffect(() => { + if (state.selectedElementID !== prevSelectedElementID.current) { + prevSelectedElementID.current = state.selectedElementID; + + if (state.selectedElementID !== null) { + let element = store.getElementByID(state.selectedElementID); + if (element !== null && element.parentID > 0) { + store.toggleIsCollapsed(element.parentID, false); } } - }, - [state.selectedElementID, store], - ); + } + }, [state.selectedElementID, store]); // Mutations to the underlying tree may impact this context (e.g. search results, selection state). - useEffect( - () => { - const handleStoreMutated = ([addedElementIDs, removedElementIDs]: [ - Array, - Map, - ]) => { - dispatchWrapper({ - type: 'HANDLE_STORE_MUTATION', - payload: [addedElementIDs, removedElementIDs], - }); - }; - - // Since this is a passive effect, the tree may have been mutated before our initial subscription. - if (store.revision !== initialRevision) { - // At the moment, we can treat this as a mutation. - // We don't know which Elements were newly added/removed, but that should be okay in this case. - // It would only impact the search state, which is unlikely to exist yet at this point. - dispatchWrapper({ - type: 'HANDLE_STORE_MUTATION', - payload: [[], new Map()], - }); - } + useEffect(() => { + const handleStoreMutated = ([addedElementIDs, removedElementIDs]: [ + Array, + Map, + ]) => { + dispatchWrapper({ + type: 'HANDLE_STORE_MUTATION', + payload: [addedElementIDs, removedElementIDs], + }); + }; + + // Since this is a passive effect, the tree may have been mutated before our initial subscription. + if (store.revision !== initialRevision) { + // At the moment, we can treat this as a mutation. + // We don't know which Elements were newly added/removed, but that should be okay in this case. + // It would only impact the search state, which is unlikely to exist yet at this point. + dispatchWrapper({ + type: 'HANDLE_STORE_MUTATION', + payload: [[], new Map()], + }); + } - store.addListener('mutated', handleStoreMutated); + store.addListener('mutated', handleStoreMutated); - return () => store.removeListener('mutated', handleStoreMutated); - }, - [dispatchWrapper, initialRevision, store], - ); + return () => store.removeListener('mutated', handleStoreMutated); + }, [dispatchWrapper, initialRevision, store]); return ( diff --git a/packages/react-devtools-shared/src/devtools/views/DevTools.js b/packages/react-devtools-shared/src/devtools/views/DevTools.js index f05cdd54e7c19..3d19c9390e682 100644 --- a/packages/react-devtools-shared/src/devtools/views/DevTools.js +++ b/packages/react-devtools-shared/src/devtools/views/DevTools.js @@ -126,18 +126,15 @@ export default function DevTools({ [enabledInspectedElementContextMenu, viewAttributeSourceFunction], ); - useEffect( - () => { - return () => { - try { - bridge.shutdown(); - } catch (error) { - // Attempting to use a disconnected port. - } - }; - }, - [bridge], - ); + useEffect(() => { + return () => { + try { + bridge.shutdown(); + } catch (error) { + // Attempting to use a disconnected port. + } + }; + }, [bridge]); return ( diff --git a/packages/react-devtools-shared/src/devtools/views/ModalDialog.js b/packages/react-devtools-shared/src/devtools/views/ModalDialog.js index bf9eada1efdf8..34aa4b85257ec 100644 --- a/packages/react-devtools-shared/src/devtools/views/ModalDialog.js +++ b/packages/react-devtools-shared/src/devtools/views/ModalDialog.js @@ -111,14 +111,11 @@ function ModalDialogImpl(_: {||}) { const {canBeDismissed, content, dispatch, title} = useContext( ModalDialogContext, ); - const dismissModal = useCallback( - () => { - if (canBeDismissed) { - dispatch({type: 'HIDE'}); - } - }, - [canBeDismissed, dispatch], - ); + const dismissModal = useCallback(() => { + if (canBeDismissed) { + dispatch({type: 'HIDE'}); + } + }, [canBeDismissed, dispatch]); const dialogRef = useRef(null); // It's important to trap click events within the dialog, diff --git a/packages/react-devtools-shared/src/devtools/views/Profiler/CommitFlamegraph.js b/packages/react-devtools-shared/src/devtools/views/Profiler/CommitFlamegraph.js index bade1502241d4..f58d18d5c5c8f 100644 --- a/packages/react-devtools-shared/src/devtools/views/Profiler/CommitFlamegraph.js +++ b/packages/react-devtools-shared/src/devtools/views/Profiler/CommitFlamegraph.js @@ -94,32 +94,26 @@ function CommitFlamegraph({chartData, commitTree, height, width}: Props) { const {lineHeight} = useContext(SettingsContext); const {selectFiber, selectedFiberID} = useContext(ProfilerContext); - const selectedChartNodeIndex = useMemo( - () => { - if (selectedFiberID === null) { - return 0; - } - // The selected node might not be in the tree for this commit, - // so it's important that we have a fallback plan. - const depth = chartData.idToDepthMap.get(selectedFiberID); - return depth !== undefined ? depth - 1 : 0; - }, - [chartData, selectedFiberID], - ); - - const selectedChartNode = useMemo( - () => { - if (selectedFiberID !== null) { - return ( - chartData.rows[selectedChartNodeIndex].find( - chartNode => chartNode.id === selectedFiberID, - ) || null - ); - } - return null; - }, - [chartData, selectedFiberID, selectedChartNodeIndex], - ); + const selectedChartNodeIndex = useMemo(() => { + if (selectedFiberID === null) { + return 0; + } + // The selected node might not be in the tree for this commit, + // so it's important that we have a fallback plan. + const depth = chartData.idToDepthMap.get(selectedFiberID); + return depth !== undefined ? depth - 1 : 0; + }, [chartData, selectedFiberID]); + + const selectedChartNode = useMemo(() => { + if (selectedFiberID !== null) { + return ( + chartData.rows[selectedChartNodeIndex].find( + chartNode => chartNode.id === selectedFiberID, + ) || null + ); + } + return null; + }, [chartData, selectedFiberID, selectedChartNodeIndex]); const itemData = useMemo( () => ({ diff --git a/packages/react-devtools-shared/src/devtools/views/Profiler/CommitTreeBuilder.js b/packages/react-devtools-shared/src/devtools/views/Profiler/CommitTreeBuilder.js index 085ec2a6dd2da..e122465c617e3 100644 --- a/packages/react-devtools-shared/src/devtools/views/Profiler/CommitTreeBuilder.js +++ b/packages/react-devtools-shared/src/devtools/views/Profiler/CommitTreeBuilder.js @@ -51,9 +51,9 @@ export function getCommitTree({ rootToCommitTreeMap.set(rootID, []); } - const commitTrees = ((rootToCommitTreeMap.get(rootID): any): Array< - CommitTree, - >); + const commitTrees = ((rootToCommitTreeMap.get( + rootID, + ): any): Array); if (commitIndex < commitTrees.length) { return commitTrees[commitIndex]; diff --git a/packages/react-devtools-shared/src/devtools/views/Profiler/InteractionListItem.js b/packages/react-devtools-shared/src/devtools/views/Profiler/InteractionListItem.js index 0e38808bb18c1..3bc6bd1f4005b 100644 --- a/packages/react-devtools-shared/src/devtools/views/Profiler/InteractionListItem.js +++ b/packages/react-devtools-shared/src/devtools/views/Profiler/InteractionListItem.js @@ -41,12 +41,9 @@ function InteractionListItem({data: itemData, index, style}: Props) { throw Error(`Could not find interaction #${index}`); } - const handleClick = useCallback( - () => { - selectInteraction(interaction.id); - }, - [interaction, selectInteraction], - ); + const handleClick = useCallback(() => { + selectInteraction(interaction.id); + }, [interaction, selectInteraction]); const commits = interactionCommits.get(interaction.id) || []; diff --git a/packages/react-devtools-shared/src/devtools/views/Profiler/Interactions.js b/packages/react-devtools-shared/src/devtools/views/Profiler/Interactions.js index e3b9b2a8e77f0..ffbd07f8863bf 100644 --- a/packages/react-devtools-shared/src/devtools/views/Profiler/Interactions.js +++ b/packages/react-devtools-shared/src/devtools/views/Profiler/Interactions.js @@ -87,45 +87,42 @@ function Interactions({height, width}: {|height: number, width: number|}) { [interactions, selectedInteractionID, selectInteraction], ); - const itemData = useMemo( - () => { - const interactionCommitSize = parseInt( - getComputedStyle((document.body: any)).getPropertyValue( - '--interaction-commit-size', - ), - 10, - ); - const interactionLabelWidth = parseInt( - getComputedStyle((document.body: any)).getPropertyValue( - '--interaction-label-width', - ), - 10, - ); + const itemData = useMemo(() => { + const interactionCommitSize = parseInt( + getComputedStyle((document.body: any)).getPropertyValue( + '--interaction-commit-size', + ), + 10, + ); + const interactionLabelWidth = parseInt( + getComputedStyle((document.body: any)).getPropertyValue( + '--interaction-label-width', + ), + 10, + ); - const labelWidth = Math.min(interactionLabelWidth, width / 5); - const timelineWidth = width - labelWidth - interactionCommitSize; + const labelWidth = Math.min(interactionLabelWidth, width / 5); + const timelineWidth = width - labelWidth - interactionCommitSize; - return { - chartData, - dataForRoot, - labelWidth, - scaleX: scale(0, chartData.lastInteractionTime, 0, timelineWidth), - selectedInteractionID, - selectCommitIndex, - selectInteraction, - selectTab, - }; - }, - [ + return { chartData, dataForRoot, + labelWidth, + scaleX: scale(0, chartData.lastInteractionTime, 0, timelineWidth), selectedInteractionID, selectCommitIndex, selectInteraction, selectTab, - width, - ], - ); + }; + }, [ + chartData, + dataForRoot, + selectedInteractionID, + selectCommitIndex, + selectInteraction, + selectTab, + width, + ]); // If a commit contains no fibers with an actualDuration > 0, // Display a fallback message. diff --git a/packages/react-devtools-shared/src/devtools/views/Profiler/ProfilerContext.js b/packages/react-devtools-shared/src/devtools/views/Profiler/ProfilerContext.js index e94d3e583ef90..4c3bc8834fa93 100644 --- a/packages/react-devtools-shared/src/devtools/views/Profiler/ProfilerContext.js +++ b/packages/react-devtools-shared/src/devtools/views/Profiler/ProfilerContext.js @@ -169,9 +169,10 @@ function ProfilerContextController({children}: Props) { store, ]); - const [isCommitFilterEnabled, setIsCommitFilterEnabled] = useLocalStorage< - boolean, - >('React::DevTools::isCommitFilterEnabled', false); + const [ + isCommitFilterEnabled, + setIsCommitFilterEnabled, + ] = useLocalStorage('React::DevTools::isCommitFilterEnabled', false); const [minCommitDuration, setMinCommitDuration] = useLocalStorage( 'minCommitDuration', 0, diff --git a/packages/react-devtools-shared/src/devtools/views/Profiler/ProfilingImportExportButtons.js b/packages/react-devtools-shared/src/devtools/views/Profiler/ProfilingImportExportButtons.js index 8f6b40199ea2e..b23d797aa3274 100644 --- a/packages/react-devtools-shared/src/devtools/views/Profiler/ProfilingImportExportButtons.js +++ b/packages/react-devtools-shared/src/devtools/views/Profiler/ProfilingImportExportButtons.js @@ -33,36 +33,33 @@ export default function ProfilingImportExportButtons() { const {dispatch: modalDialogDispatch} = useContext(ModalDialogContext); - const downloadData = useCallback( - () => { - if (rootID === null) { - return; - } + const downloadData = useCallback(() => { + if (rootID === null) { + return; + } - if (profilingData !== null && downloadRef.current !== null) { - const profilingDataExport = prepareProfilingDataExport(profilingData); - const date = new Date(); - const dateString = date - .toLocaleDateString(undefined, { - year: 'numeric', - month: '2-digit', - day: '2-digit', - }) - .replace(/\//g, '-'); - const timeString = date - .toLocaleTimeString(undefined, { - hour12: false, - }) - .replace(/:/g, '-'); - downloadFile( - downloadRef.current, - `profiling-data.${dateString}.${timeString}.json`, - JSON.stringify(profilingDataExport, null, 2), - ); - } - }, - [rootID, profilingData], - ); + if (profilingData !== null && downloadRef.current !== null) { + const profilingDataExport = prepareProfilingDataExport(profilingData); + const date = new Date(); + const dateString = date + .toLocaleDateString(undefined, { + year: 'numeric', + month: '2-digit', + day: '2-digit', + }) + .replace(/\//g, '-'); + const timeString = date + .toLocaleTimeString(undefined, { + hour12: false, + }) + .replace(/:/g, '-'); + downloadFile( + downloadRef.current, + `profiling-data.${dateString}.${timeString}.json`, + JSON.stringify(profilingDataExport, null, 2), + ); + } + }, [rootID, profilingData]); const uploadData = useCallback(() => { if (inputRef.current !== null) { @@ -70,41 +67,38 @@ export default function ProfilingImportExportButtons() { } }, []); - const handleFiles = useCallback( - () => { - const input = inputRef.current; - if (input !== null && input.files.length > 0) { - const fileReader = new FileReader(); - fileReader.addEventListener('load', () => { - try { - const raw = ((fileReader.result: any): string); - const profilingDataExport = ((JSON.parse( - raw, - ): any): ProfilingDataExport); - profilerStore.profilingData = prepareProfilingDataFrontendFromExport( - profilingDataExport, - ); - } catch (error) { - modalDialogDispatch({ - type: 'SHOW', - title: 'Import failed', - content: ( - -
The profiling data you selected cannot be imported.
- {error !== null && ( -
{error.message}
- )} -
- ), - }); - } - }); - // TODO (profiling) Handle fileReader errors. - fileReader.readAsText(input.files[0]); - } - }, - [modalDialogDispatch, profilerStore], - ); + const handleFiles = useCallback(() => { + const input = inputRef.current; + if (input !== null && input.files.length > 0) { + const fileReader = new FileReader(); + fileReader.addEventListener('load', () => { + try { + const raw = ((fileReader.result: any): string); + const profilingDataExport = ((JSON.parse( + raw, + ): any): ProfilingDataExport); + profilerStore.profilingData = prepareProfilingDataFrontendFromExport( + profilingDataExport, + ); + } catch (error) { + modalDialogDispatch({ + type: 'SHOW', + title: 'Import failed', + content: ( + +
The profiling data you selected cannot be imported.
+ {error !== null && ( +
{error.message}
+ )} +
+ ), + }); + } + }); + // TODO (profiling) Handle fileReader errors. + fileReader.readAsText(input.files[0]); + } + }, [modalDialogDispatch, profilerStore]); return ( diff --git a/packages/react-devtools-shared/src/devtools/views/Profiler/ReloadAndProfileButton.js b/packages/react-devtools-shared/src/devtools/views/Profiler/ReloadAndProfileButton.js index a8cefc1981935..d3772ead4d167 100644 --- a/packages/react-devtools-shared/src/devtools/views/Profiler/ReloadAndProfileButton.js +++ b/packages/react-devtools-shared/src/devtools/views/Profiler/ReloadAndProfileButton.js @@ -39,22 +39,20 @@ export default function ReloadAndProfileButton() { }), [store], ); - const {recordChangeDescriptions, supportsReloadAndProfile} = useSubscription< - SubscriptionData, - >(subscription); + const { + recordChangeDescriptions, + supportsReloadAndProfile, + } = useSubscription(subscription); - const reloadAndProfile = useCallback( - () => { - // TODO If we want to support reload-and-profile for e.g. React Native, - // we might need to also start profiling here before reloading the app (since DevTools itself isn't reloaded). - // We'd probably want to do this before reloading though, to avoid sending a message on a disconnected port in the browser. - // For now, let's just skip doing it entirely to avoid paying snapshot costs for data we don't need. - // startProfiling(); + const reloadAndProfile = useCallback(() => { + // TODO If we want to support reload-and-profile for e.g. React Native, + // we might need to also start profiling here before reloading the app (since DevTools itself isn't reloaded). + // We'd probably want to do this before reloading though, to avoid sending a message on a disconnected port in the browser. + // For now, let's just skip doing it entirely to avoid paying snapshot costs for data we don't need. + // startProfiling(); - bridge.send('reloadAndProfile', recordChangeDescriptions); - }, - [bridge, recordChangeDescriptions], - ); + bridge.send('reloadAndProfile', recordChangeDescriptions); + }, [bridge, recordChangeDescriptions]); if (!supportsReloadAndProfile) { return null; diff --git a/packages/react-devtools-shared/src/devtools/views/Profiler/SnapshotCommitList.js b/packages/react-devtools-shared/src/devtools/views/Profiler/SnapshotCommitList.js index 208d4ed5178a9..1723b9d5c7fe1 100644 --- a/packages/react-devtools-shared/src/devtools/views/Profiler/SnapshotCommitList.js +++ b/packages/react-devtools-shared/src/devtools/views/Profiler/SnapshotCommitList.js @@ -87,17 +87,14 @@ function List({ const prevCommitIndexRef = useRef(null); // Make sure a newly selected snapshot is fully visible within the list. - useEffect( - () => { - if (selectedFilteredCommitIndex !== prevCommitIndexRef.current) { - prevCommitIndexRef.current = selectedFilteredCommitIndex; - if (selectedFilteredCommitIndex !== null && listRef.current !== null) { - listRef.current.scrollToItem(selectedFilteredCommitIndex); - } + useEffect(() => { + if (selectedFilteredCommitIndex !== prevCommitIndexRef.current) { + prevCommitIndexRef.current = selectedFilteredCommitIndex; + if (selectedFilteredCommitIndex !== null && listRef.current !== null) { + listRef.current.scrollToItem(selectedFilteredCommitIndex); } - }, - [listRef, selectedFilteredCommitIndex], - ); + } + }, [listRef, selectedFilteredCommitIndex]); // When the mouse is down, dragging over a commit should auto-select it. // This provides a nice way for users to swipe across a range of commits to compare them. @@ -108,21 +105,18 @@ function List({ const handleMouseUp = useCallback(() => { setIsMouseDown(false); }, []); - useEffect( - () => { - if (divRef.current === null) { - return () => {}; - } + useEffect(() => { + if (divRef.current === null) { + return () => {}; + } - // It's important to listen to the ownerDocument to support the browser extension. - // Here we use portals to render individual tabs (e.g. Profiler), - // and the root document might belong to a different window. - const ownerDocument = divRef.current.ownerDocument; - ownerDocument.addEventListener('mouseup', handleMouseUp); - return () => ownerDocument.removeEventListener('mouseup', handleMouseUp); - }, - [divRef, handleMouseUp], - ); + // It's important to listen to the ownerDocument to support the browser extension. + // Here we use portals to render individual tabs (e.g. Profiler), + // and the root document might belong to a different window. + const ownerDocument = divRef.current.ownerDocument; + ownerDocument.addEventListener('mouseup', handleMouseUp); + return () => ownerDocument.removeEventListener('mouseup', handleMouseUp); + }, [divRef, handleMouseUp]); const itemSize = useMemo( () => Math.max(minBarWidth, width / filteredCommitIndices.length), diff --git a/packages/react-devtools-shared/src/devtools/views/Profiler/SnapshotSelector.js b/packages/react-devtools-shared/src/devtools/views/Profiler/SnapshotSelector.js index 41979cee6b9f5..41d5e7a77ed03 100644 --- a/packages/react-devtools-shared/src/devtools/views/Profiler/SnapshotSelector.js +++ b/packages/react-devtools-shared/src/devtools/views/Profiler/SnapshotSelector.js @@ -55,19 +55,16 @@ export default function SnapshotSelector(_: Props) { const numFilteredCommits = filteredCommitIndices.length; // Map the (unfiltered) selected commit index to an index within the filtered data. - const selectedFilteredCommitIndex = useMemo( - () => { - if (selectedCommitIndex !== null) { - for (let i = 0; i < filteredCommitIndices.length; i++) { - if (filteredCommitIndices[i] === selectedCommitIndex) { - return i; - } + const selectedFilteredCommitIndex = useMemo(() => { + if (selectedCommitIndex !== null) { + for (let i = 0; i < filteredCommitIndices.length; i++) { + if (filteredCommitIndices[i] === selectedCommitIndex) { + return i; } } - return null; - }, - [filteredCommitIndices, selectedCommitIndex], - ); + } + return null; + }, [filteredCommitIndices, selectedCommitIndex]); // TODO (ProfilerContext) This should be managed by the context controller (reducer). // It doesn't currently know about the filtered commits though (since it doesn't suspend). @@ -93,26 +90,20 @@ export default function SnapshotSelector(_: Props) { numFilteredCommits; } - const viewNextCommit = useCallback( - () => { - let nextCommitIndex = ((selectedFilteredCommitIndex: any): number) + 1; - if (nextCommitIndex === filteredCommitIndices.length) { - nextCommitIndex = 0; - } - selectCommitIndex(filteredCommitIndices[nextCommitIndex]); - }, - [selectedFilteredCommitIndex, filteredCommitIndices, selectCommitIndex], - ); - const viewPrevCommit = useCallback( - () => { - let nextCommitIndex = ((selectedFilteredCommitIndex: any): number) - 1; - if (nextCommitIndex < 0) { - nextCommitIndex = filteredCommitIndices.length - 1; - } - selectCommitIndex(filteredCommitIndices[nextCommitIndex]); - }, - [selectedFilteredCommitIndex, filteredCommitIndices, selectCommitIndex], - ); + const viewNextCommit = useCallback(() => { + let nextCommitIndex = ((selectedFilteredCommitIndex: any): number) + 1; + if (nextCommitIndex === filteredCommitIndices.length) { + nextCommitIndex = 0; + } + selectCommitIndex(filteredCommitIndices[nextCommitIndex]); + }, [selectedFilteredCommitIndex, filteredCommitIndices, selectCommitIndex]); + const viewPrevCommit = useCallback(() => { + let nextCommitIndex = ((selectedFilteredCommitIndex: any): number) - 1; + if (nextCommitIndex < 0) { + nextCommitIndex = filteredCommitIndices.length - 1; + } + selectCommitIndex(filteredCommitIndices[nextCommitIndex]); + }, [selectedFilteredCommitIndex, filteredCommitIndices, selectCommitIndex]); const handleKeyDown = useCallback( event => { diff --git a/packages/react-devtools-shared/src/devtools/views/Settings/ComponentsSettings.js b/packages/react-devtools-shared/src/devtools/views/Settings/ComponentsSettings.js index 1d4697abe52ed..8244a4b83d622 100644 --- a/packages/react-devtools-shared/src/devtools/views/Settings/ComponentsSettings.js +++ b/packages/react-devtools-shared/src/devtools/views/Settings/ComponentsSettings.js @@ -229,13 +229,10 @@ export default function ComponentsSettings(_: {||}) { // The Store will avoid doing any expensive work unless they've changed. // We just want to batch the work in the event that they do change. const componentFiltersRef = useRef>(componentFilters); - useEffect( - () => { - componentFiltersRef.current = componentFilters; - return () => {}; - }, - [componentFilters], - ); + useEffect(() => { + componentFiltersRef.current = componentFilters; + return () => {}; + }, [componentFilters]); useEffect( () => () => { store.componentFilters = [...componentFiltersRef.current]; @@ -282,8 +279,8 @@ export default function ComponentsSettings(_: {||}) { componentFilter.isValid === false ? 'Filter invalid' : componentFilter.isEnabled - ? 'Filter enabled' - : 'Filter disabled' + ? 'Filter enabled' + : 'Filter disabled' }> (LOCAL_STORAGE_SHOULD_PATCH_CONSOLE_KEY, true); - const [traceUpdatesEnabled, setTraceUpdatesEnabled] = useLocalStorage< - boolean, - >(LOCAL_STORAGE_TRACE_UPDATES_ENABLED_KEY, false); + const [ + appendComponentStack, + setAppendComponentStack, + ] = useLocalStorage(LOCAL_STORAGE_SHOULD_PATCH_CONSOLE_KEY, true); + const [ + traceUpdatesEnabled, + setTraceUpdatesEnabled, + ] = useLocalStorage(LOCAL_STORAGE_TRACE_UPDATES_ENABLED_KEY, false); - const documentElements = useMemo( - () => { - const array: Array = [ - ((document.documentElement: any): HTMLElement), - ]; - if (componentsPortalContainer != null) { - array.push( - ((componentsPortalContainer.ownerDocument - .documentElement: any): HTMLElement), - ); - } - if (profilerPortalContainer != null) { - array.push( - ((profilerPortalContainer.ownerDocument - .documentElement: any): HTMLElement), - ); - } - return array; - }, - [componentsPortalContainer, profilerPortalContainer], - ); + const documentElements = useMemo(() => { + const array: Array = [ + ((document.documentElement: any): HTMLElement), + ]; + if (componentsPortalContainer != null) { + array.push( + ((componentsPortalContainer.ownerDocument + .documentElement: any): HTMLElement), + ); + } + if (profilerPortalContainer != null) { + array.push( + ((profilerPortalContainer.ownerDocument + .documentElement: any): HTMLElement), + ); + } + return array; + }, [componentsPortalContainer, profilerPortalContainer]); - useLayoutEffect( - () => { - switch (displayDensity) { - case 'comfortable': - updateDisplayDensity('comfortable', documentElements); - break; - case 'compact': - updateDisplayDensity('compact', documentElements); - break; - default: - throw Error(`Unsupported displayDensity value "${displayDensity}"`); - } - }, - [displayDensity, documentElements], - ); + useLayoutEffect(() => { + switch (displayDensity) { + case 'comfortable': + updateDisplayDensity('comfortable', documentElements); + break; + case 'compact': + updateDisplayDensity('compact', documentElements); + break; + default: + throw Error(`Unsupported displayDensity value "${displayDensity}"`); + } + }, [displayDensity, documentElements]); - useLayoutEffect( - () => { - switch (theme) { - case 'light': - updateThemeVariables('light', documentElements); - break; - case 'dark': - updateThemeVariables('dark', documentElements); - break; - case 'auto': - updateThemeVariables(browserTheme, documentElements); - break; - default: - throw Error(`Unsupported theme value "${theme}"`); - } - }, - [browserTheme, theme, documentElements], - ); + useLayoutEffect(() => { + switch (theme) { + case 'light': + updateThemeVariables('light', documentElements); + break; + case 'dark': + updateThemeVariables('dark', documentElements); + break; + case 'auto': + updateThemeVariables(browserTheme, documentElements); + break; + default: + throw Error(`Unsupported theme value "${theme}"`); + } + }, [browserTheme, theme, documentElements]); - useEffect( - () => { - bridge.send('updateAppendComponentStack', appendComponentStack); - }, - [bridge, appendComponentStack], - ); + useEffect(() => { + bridge.send('updateAppendComponentStack', appendComponentStack); + }, [bridge, appendComponentStack]); - useEffect( - () => { - bridge.send('setTraceUpdatesEnabled', traceUpdatesEnabled); - }, - [bridge, traceUpdatesEnabled], - ); + useEffect(() => { + bridge.send('setTraceUpdatesEnabled', traceUpdatesEnabled); + }, [bridge, traceUpdatesEnabled]); const value = useMemo( () => ({ diff --git a/packages/react-devtools-shared/src/devtools/views/Settings/SettingsModal.js b/packages/react-devtools-shared/src/devtools/views/Settings/SettingsModal.js index 5ac993a919248..e76dae6518203 100644 --- a/packages/react-devtools-shared/src/devtools/views/Settings/SettingsModal.js +++ b/packages/react-devtools-shared/src/devtools/views/Settings/SettingsModal.js @@ -75,14 +75,11 @@ function SettingsModalImpl(_: {||}) { const modalRef = useRef(null); useModalDismissSignal(modalRef, dismissModal); - useEffect( - () => { - if (modalRef.current !== null) { - modalRef.current.focus(); - } - }, - [modalRef], - ); + useEffect(() => { + if (modalRef.current !== null) { + modalRef.current.focus(); + } + }, [modalRef]); let view = null; switch (selectedTabID) { diff --git a/packages/react-devtools-shared/src/devtools/views/UnsupportedVersionDialog.js b/packages/react-devtools-shared/src/devtools/views/UnsupportedVersionDialog.js index 652c4904c2246..1f35eee3c85e4 100644 --- a/packages/react-devtools-shared/src/devtools/views/UnsupportedVersionDialog.js +++ b/packages/react-devtools-shared/src/devtools/views/UnsupportedVersionDialog.js @@ -22,35 +22,32 @@ export default function UnsupportedVersionDialog(_: {||}) { const store = useContext(StoreContext); const [state, setState] = useState('dialog-not-shown'); - useEffect( - () => { - if (state === 'dialog-not-shown') { - const showDialog = () => { - batchedUpdates(() => { - setState('show-dialog'); - dispatch({ - canBeDismissed: true, - type: 'SHOW', - content: , - }); + useEffect(() => { + if (state === 'dialog-not-shown') { + const showDialog = () => { + batchedUpdates(() => { + setState('show-dialog'); + dispatch({ + canBeDismissed: true, + type: 'SHOW', + content: , }); - }; + }); + }; - if (store.unsupportedRendererVersionDetected) { - showDialog(); - } else { - store.addListener('unsupportedRendererVersionDetected', showDialog); - return () => { - store.removeListener( - 'unsupportedRendererVersionDetected', - showDialog, - ); - }; - } + if (store.unsupportedRendererVersionDetected) { + showDialog(); + } else { + store.addListener('unsupportedRendererVersionDetected', showDialog); + return () => { + store.removeListener( + 'unsupportedRendererVersionDetected', + showDialog, + ); + }; } - }, - [state, store], - ); + } + }, [state, store]); return null; } @@ -74,7 +71,8 @@ function DialogContent(_: {||}) { rel="noopener noreferrer" href={UNSUPPORTED_VERSION_URL}> install an older version of the extension - . + + .

diff --git a/packages/react-devtools-shared/src/devtools/views/WarnIfLegacyBackendDetected.js b/packages/react-devtools-shared/src/devtools/views/WarnIfLegacyBackendDetected.js index cdcee4758ab92..cb4933f8dbda2 100644 --- a/packages/react-devtools-shared/src/devtools/views/WarnIfLegacyBackendDetected.js +++ b/packages/react-devtools-shared/src/devtools/views/WarnIfLegacyBackendDetected.js @@ -20,58 +20,55 @@ export default function WarnIfLegacyBackendDetected(_: {||}) { // Detect pairing with legacy v3 backend. // We do this by listening to a message that it broadcasts but the v4 backend doesn't. // In this case the frontend should show upgrade instructions. - useEffect( - () => { - // Wall.listen returns a cleanup function - let unlisten = bridge.wall.listen(message => { - switch (message.type) { - case 'call': - case 'event': - case 'many-events': - // Any of these types indicate the v3 backend. - dispatch({ - canBeDismissed: false, - type: 'SHOW', - title: 'DevTools v4 is incompatible with this version of React', - content: , - }); + useEffect(() => { + // Wall.listen returns a cleanup function + let unlisten = bridge.wall.listen(message => { + switch (message.type) { + case 'call': + case 'event': + case 'many-events': + // Any of these types indicate the v3 backend. + dispatch({ + canBeDismissed: false, + type: 'SHOW', + title: 'DevTools v4 is incompatible with this version of React', + content: , + }); - // Once we've identified the backend version, it's safe to unsubscribe. - if (typeof unlisten === 'function') { - unlisten(); - unlisten = null; - } - break; - default: - break; - } + // Once we've identified the backend version, it's safe to unsubscribe. + if (typeof unlisten === 'function') { + unlisten(); + unlisten = null; + } + break; + default: + break; + } - switch (message.event) { - case 'isBackendStorageAPISupported': - case 'isNativeStyleEditorSupported': - case 'operations': - case 'overrideComponentFilters': - // Any of these is sufficient to indicate a v4 backend. - // Once we've identified the backend version, it's safe to unsubscribe. - if (typeof unlisten === 'function') { - unlisten(); - unlisten = null; - } - break; - default: - break; - } - }); + switch (message.event) { + case 'isBackendStorageAPISupported': + case 'isNativeStyleEditorSupported': + case 'operations': + case 'overrideComponentFilters': + // Any of these is sufficient to indicate a v4 backend. + // Once we've identified the backend version, it's safe to unsubscribe. + if (typeof unlisten === 'function') { + unlisten(); + unlisten = null; + } + break; + default: + break; + } + }); - return () => { - if (typeof unlisten === 'function') { - unlisten(); - unlisten = null; - } - }; - }, - [bridge, dispatch], - ); + return () => { + if (typeof unlisten === 'function') { + unlisten(); + unlisten = null; + } + }; + }, [bridge, dispatch]); return null; } diff --git a/packages/react-devtools-shared/src/devtools/views/hooks.js b/packages/react-devtools-shared/src/devtools/views/hooks.js index 693f72535bbe5..62cafbfed316f 100644 --- a/packages/react-devtools-shared/src/devtools/views/hooks.js +++ b/packages/react-devtools-shared/src/devtools/views/hooks.js @@ -112,30 +112,27 @@ export function useIsOverflowing( const [isOverflowing, setIsOverflowing] = useState(false); // It's important to use a layout effect, so that we avoid showing a flash of overflowed content. - useLayoutEffect( - () => { - if (containerRef.current === null) { - return () => {}; - } + useLayoutEffect(() => { + if (containerRef.current === null) { + return () => {}; + } - const container = ((containerRef.current: any): HTMLDivElement); + const container = ((containerRef.current: any): HTMLDivElement); - const handleResize = throttle( - () => setIsOverflowing(container.clientWidth <= totalChildWidth), - 100, - ); + const handleResize = throttle( + () => setIsOverflowing(container.clientWidth <= totalChildWidth), + 100, + ); - handleResize(); + handleResize(); - // It's important to listen to the ownerDocument.defaultView to support the browser extension. - // Here we use portals to render individual tabs (e.g. Profiler), - // and the root document might belong to a different window. - const ownerWindow = container.ownerDocument.defaultView; - ownerWindow.addEventListener('resize', handleResize); - return () => ownerWindow.removeEventListener('resize', handleResize); - }, - [containerRef, totalChildWidth], - ); + // It's important to listen to the ownerDocument.defaultView to support the browser extension. + // Here we use portals to render individual tabs (e.g. Profiler), + // and the root document might belong to a different window. + const ownerWindow = container.ownerDocument.defaultView; + ownerWindow.addEventListener('resize', handleResize); + return () => ownerWindow.removeEventListener('resize', handleResize); + }, [containerRef, totalChildWidth]); return isOverflowing; } @@ -145,24 +142,21 @@ export function useLocalStorage( key: string, initialValue: T | (() => T), ): [T, (value: T | (() => T)) => void] { - const getValueFromLocalStorage = useCallback( - () => { - try { - const item = localStorageGetItem(key); - if (item != null) { - return JSON.parse(item); - } - } catch (error) { - console.log(error); - } - if (typeof initialValue === 'function') { - return ((initialValue: any): () => T)(); - } else { - return initialValue; + const getValueFromLocalStorage = useCallback(() => { + try { + const item = localStorageGetItem(key); + if (item != null) { + return JSON.parse(item); } - }, - [initialValue, key], - ); + } catch (error) { + console.log(error); + } + if (typeof initialValue === 'function') { + return ((initialValue: any): () => T)(); + } else { + return initialValue; + } + }, [initialValue, key]); const [storedValue, setStoredValue] = useState(getValueFromLocalStorage); @@ -182,23 +176,20 @@ export function useLocalStorage( // Listen for changes to this local storage value made from other windows. // This enables the e.g. "⚛️ Elements" tab to update in response to changes from "⚛️ Settings". - useLayoutEffect( - () => { - const onStorage = event => { - const newValue = getValueFromLocalStorage(); - if (key === event.key && storedValue !== newValue) { - setValue(newValue); - } - }; + useLayoutEffect(() => { + const onStorage = event => { + const newValue = getValueFromLocalStorage(); + if (key === event.key && storedValue !== newValue) { + setValue(newValue); + } + }; - window.addEventListener('storage', onStorage); + window.addEventListener('storage', onStorage); - return () => { - window.removeEventListener('storage', onStorage); - }; - }, - [getValueFromLocalStorage, key, storedValue, setValue], - ); + return () => { + window.removeEventListener('storage', onStorage); + }; + }, [getValueFromLocalStorage, key, storedValue, setValue]); return [storedValue, setValue]; } @@ -208,47 +199,44 @@ export function useModalDismissSignal( dismissCallback: () => void, dismissOnClickOutside?: boolean = true, ): void { - useEffect( - () => { - if (modalRef.current === null) { - return () => {}; - } - - const handleDocumentKeyDown = ({key}: any) => { - if (key === 'Escape') { - dismissCallback(); - } - }; - - const handleDocumentClick = (event: any) => { - // $FlowFixMe - if ( - modalRef.current !== null && - !modalRef.current.contains(event.target) - ) { - event.stopPropagation(); - event.preventDefault(); - - dismissCallback(); - } - }; + useEffect(() => { + if (modalRef.current === null) { + return () => {}; + } - // It's important to listen to the ownerDocument to support the browser extension. - // Here we use portals to render individual tabs (e.g. Profiler), - // and the root document might belong to a different window. - const ownerDocument = modalRef.current.ownerDocument; - ownerDocument.addEventListener('keydown', handleDocumentKeyDown); - if (dismissOnClickOutside) { - ownerDocument.addEventListener('click', handleDocumentClick); + const handleDocumentKeyDown = ({key}: any) => { + if (key === 'Escape') { + dismissCallback(); + } + }; + + const handleDocumentClick = (event: any) => { + // $FlowFixMe + if ( + modalRef.current !== null && + !modalRef.current.contains(event.target) + ) { + event.stopPropagation(); + event.preventDefault(); + + dismissCallback(); } + }; + + // It's important to listen to the ownerDocument to support the browser extension. + // Here we use portals to render individual tabs (e.g. Profiler), + // and the root document might belong to a different window. + const ownerDocument = modalRef.current.ownerDocument; + ownerDocument.addEventListener('keydown', handleDocumentKeyDown); + if (dismissOnClickOutside) { + ownerDocument.addEventListener('click', handleDocumentClick); + } - return () => { - ownerDocument.removeEventListener('keydown', handleDocumentKeyDown); - ownerDocument.removeEventListener('click', handleDocumentClick); - }; - }, - [modalRef, dismissCallback, dismissOnClickOutside], - ); + return () => { + ownerDocument.removeEventListener('keydown', handleDocumentKeyDown); + ownerDocument.removeEventListener('click', handleDocumentClick); + }; + }, [modalRef, dismissCallback, dismissOnClickOutside]); } // Copied from https://github.com/facebook/react/pull/15022 @@ -276,42 +264,39 @@ export function useSubscription({ }); } - useEffect( - () => { - let didUnsubscribe = false; + useEffect(() => { + let didUnsubscribe = false; - const checkForUpdates = () => { - if (didUnsubscribe) { - return; + const checkForUpdates = () => { + if (didUnsubscribe) { + return; + } + + setState(prevState => { + if ( + prevState.getCurrentValue !== getCurrentValue || + prevState.subscribe !== subscribe + ) { + return prevState; } - setState(prevState => { - if ( - prevState.getCurrentValue !== getCurrentValue || - prevState.subscribe !== subscribe - ) { - return prevState; - } - - const value = getCurrentValue(); - if (prevState.value === value) { - return prevState; - } - - return {...prevState, value}; - }); - }; - const unsubscribe = subscribe(checkForUpdates); + const value = getCurrentValue(); + if (prevState.value === value) { + return prevState; + } - checkForUpdates(); + return {...prevState, value}; + }); + }; + const unsubscribe = subscribe(checkForUpdates); - return () => { - didUnsubscribe = true; - unsubscribe(); - }; - }, - [getCurrentValue, subscribe], - ); + checkForUpdates(); + + return () => { + didUnsubscribe = true; + unsubscribe(); + }; + }, [getCurrentValue, subscribe]); return state.value; } diff --git a/packages/react-devtools-shell/src/app/Hydration/index.js b/packages/react-devtools-shell/src/app/Hydration/index.js index 914bf54ccc071..d2be0e6901737 100644 --- a/packages/react-devtools-shell/src/app/Hydration/index.js +++ b/packages/react-devtools-shell/src/app/Hydration/index.js @@ -17,8 +17,16 @@ typedArray[1] = 2; typedArray[2] = 3; const arrayOfArrays = [ - [['a', 'b', 'c'], ['d', 'e', 'f'], ['h', 'i', 'j']], - [['k', 'l', 'm'], ['n', 'o', 'p'], ['q', 'r', 's']], + [ + ['a', 'b', 'c'], + ['d', 'e', 'f'], + ['h', 'i', 'j'], + ], + [ + ['k', 'l', 'm'], + ['n', 'o', 'p'], + ['q', 'r', 's'], + ], [['t', 'u', 'v'], ['w', 'x', 'y'], ['z']], [], ]; diff --git a/packages/react-devtools-shell/src/app/InspectableElements/UnserializableProps.js b/packages/react-devtools-shell/src/app/InspectableElements/UnserializableProps.js index effe7f14a348f..561aad203449d 100644 --- a/packages/react-devtools-shell/src/app/InspectableElements/UnserializableProps.js +++ b/packages/react-devtools-shell/src/app/InspectableElements/UnserializableProps.js @@ -11,9 +11,15 @@ import React from 'react'; import Immutable from 'immutable'; const set = new Set(['abc', 123]); -const map = new Map([['name', 'Brian'], ['food', 'sushi']]); +const map = new Map([ + ['name', 'Brian'], + ['food', 'sushi'], +]); const setOfSets = new Set([new Set(['a', 'b', 'c']), new Set([1, 2, 3])]); -const mapOfMaps = new Map([['first', map], ['second', map]]); +const mapOfMaps = new Map([ + ['first', map], + ['second', map], +]); const typedArray = Int8Array.from([100, -100, 0]); const arrayBuffer = typedArray.buffer; const dataView = new DataView(arrayBuffer); diff --git a/packages/react-devtools-shell/src/app/InteractionTracing/index.js b/packages/react-devtools-shell/src/app/InteractionTracing/index.js index be44460bb56df..9d713d8fe5bcd 100644 --- a/packages/react-devtools-shell/src/app/InteractionTracing/index.js +++ b/packages/react-devtools-shell/src/app/InteractionTracing/index.js @@ -18,66 +18,54 @@ export default function InteractionTracing() { const [count, setCount] = useState(0); const [shouldCascade, setShouldCascade] = useState(false); - const handleUpdate = useCallback( - () => { - trace('count', performance.now(), () => { - setTimeout( - wrap(() => { + const handleUpdate = useCallback(() => { + trace('count', performance.now(), () => { + setTimeout( + wrap(() => { + setCount(count + 1); + }), + count * 100, + ); + }); + }, [count]); + + const handleCascadingUpdate = useCallback(() => { + trace('cascade', performance.now(), () => { + setTimeout( + wrap(() => { + batchedUpdates(() => { setCount(count + 1); - }), - count * 100, - ); - }); - }, - [count], - ); + setShouldCascade(true); + }); + }), + count * 100, + ); + }); + }, [count]); - const handleCascadingUpdate = useCallback( - () => { - trace('cascade', performance.now(), () => { + const handleMultiple = useCallback(() => { + trace('first', performance.now(), () => { + trace('second', performance.now(), () => { setTimeout( wrap(() => { - batchedUpdates(() => { - setCount(count + 1); - setShouldCascade(true); - }); + setCount(count + 1); }), count * 100, ); }); - }, - [count], - ); + }); + }, [count]); - const handleMultiple = useCallback( - () => { - trace('first', performance.now(), () => { - trace('second', performance.now(), () => { - setTimeout( - wrap(() => { - setCount(count + 1); - }), - count * 100, - ); - }); - }); - }, - [count], - ); - - useEffect( - () => { - if (shouldCascade) { - setTimeout( - wrap(() => { - setShouldCascade(false); - }), - count * 100, - ); - } - }, - [count, shouldCascade], - ); + useEffect(() => { + if (shouldCascade) { + setTimeout( + wrap(() => { + setShouldCascade(false); + }), + count * 100, + ); + } + }, [count, shouldCascade]); return ( diff --git a/packages/react-devtools-shell/src/app/ToDoList/List.js b/packages/react-devtools-shell/src/app/ToDoList/List.js index 1decfb28e7255..e3fee20080797 100644 --- a/packages/react-devtools-shell/src/app/ToDoList/List.js +++ b/packages/react-devtools-shell/src/app/ToDoList/List.js @@ -28,23 +28,20 @@ export default function List(props: Props) { ]); const [uid, setUID] = useState(4); - const handleClick = useCallback( - () => { - if (newItemText !== '') { - setItems([ - ...items, - { - id: uid, - isComplete: false, - text: newItemText, - }, - ]); - setUID(uid + 1); - setNewItemText(''); - } - }, - [newItemText, items, uid], - ); + const handleClick = useCallback(() => { + if (newItemText !== '') { + setItems([ + ...items, + { + id: uid, + isComplete: false, + text: newItemText, + }, + ]); + setUID(uid + 1); + setNewItemText(''); + } + }, [newItemText, items, uid]); const handleKeyPress = useCallback( event => { diff --git a/packages/react-devtools-shell/src/app/ToDoList/ListItem.js b/packages/react-devtools-shell/src/app/ToDoList/ListItem.js index 6d0a759169cdb..9ef1afffdf44c 100644 --- a/packages/react-devtools-shell/src/app/ToDoList/ListItem.js +++ b/packages/react-devtools-shell/src/app/ToDoList/ListItem.js @@ -19,19 +19,13 @@ type Props = {| |}; function ListItem({item, removeItem, toggleItem}: Props) { - const handleDelete = useCallback( - () => { - removeItem(item); - }, - [item, removeItem], - ); + const handleDelete = useCallback(() => { + removeItem(item); + }, [item, removeItem]); - const handleToggle = useCallback( - () => { - toggleItem(item); - }, - [item, toggleItem], - ); + const handleToggle = useCallback(() => { + toggleItem(item); + }, [item, toggleItem]); return (
  • diff --git a/packages/react-dom/src/__tests__/ReactComponentLifeCycle-test.js b/packages/react-dom/src/__tests__/ReactComponentLifeCycle-test.js index 3b124941d7f15..6b51eb6a12560 100644 --- a/packages/react-dom/src/__tests__/ReactComponentLifeCycle-test.js +++ b/packages/react-dom/src/__tests__/ReactComponentLifeCycle-test.js @@ -1148,9 +1148,11 @@ describe('ReactComponentLifeCycle', () => { render() { childInstance = this; return ( -
    {`remote:${ - this.state.remote - }, local:${this.state.local}`}
    +
    {`remote:${this.state.remote}, local:${this.state.local}`}
    ); } } @@ -1197,17 +1199,13 @@ describe('ReactComponentLifeCycle', () => { } getSnapshotBeforeUpdate(prevProps, prevState) { log.push( - `getSnapshotBeforeUpdate() prevProps:${prevProps.value} prevState:${ - prevState.value - }`, + `getSnapshotBeforeUpdate() prevProps:${prevProps.value} prevState:${prevState.value}`, ); return 'abc'; } componentDidUpdate(prevProps, prevState, snapshot) { log.push( - `componentDidUpdate() prevProps:${prevProps.value} prevState:${ - prevState.value - } snapshot:${snapshot}`, + `componentDidUpdate() prevProps:${prevProps.value} prevState:${prevState.value} snapshot:${snapshot}`, ); } render() { diff --git a/packages/react-dom/src/__tests__/ReactCompositeComponent-test.js b/packages/react-dom/src/__tests__/ReactCompositeComponent-test.js index 5994813d69f27..908d418cac7ef 100644 --- a/packages/react-dom/src/__tests__/ReactCompositeComponent-test.js +++ b/packages/react-dom/src/__tests__/ReactCompositeComponent-test.js @@ -165,7 +165,9 @@ describe('ReactCompositeComponent', () => { // Old API based on heuristic let container = document.createElement('div'); container.innerHTML = markup; - expect(() => ReactDOM.render(, container)).toWarnDev( + expect(() => + ReactDOM.render(, container), + ).toWarnDev( 'render(): Calling ReactDOM.render() to hydrate server-rendered markup ' + 'will stop working in React v17. Replace the ReactDOM.render() call ' + 'with ReactDOM.hydrate() if you want React to attach to the server HTML.', diff --git a/packages/react-dom/src/__tests__/ReactDOMComponent-test.js b/packages/react-dom/src/__tests__/ReactDOMComponent-test.js index acf81a30118e2..219b2346d2f5e 100644 --- a/packages/react-dom/src/__tests__/ReactDOMComponent-test.js +++ b/packages/react-dom/src/__tests__/ReactDOMComponent-test.js @@ -182,24 +182,21 @@ describe('ReactDOMComponent', () => { it('should warn for unknown string event handlers', () => { const container = document.createElement('div'); expect(() => - ReactDOM.render(
    , container), + ReactDOM.render(
    , container), ).toErrorDev( 'Warning: Unknown event handler property `onUnknown`. It will be ignored.\n in div (at **)', ); expect(container.firstChild.hasAttribute('onUnknown')).toBe(false); expect(container.firstChild.onUnknown).toBe(undefined); expect(() => - ReactDOM.render(
    , container), + ReactDOM.render(
    , container), ).toErrorDev( 'Warning: Unknown event handler property `onunknown`. It will be ignored.\n in div (at **)', ); expect(container.firstChild.hasAttribute('onunknown')).toBe(false); expect(container.firstChild.onunknown).toBe(undefined); expect(() => - ReactDOM.render( -
    , - container, - ), + ReactDOM.render(
    , container), ).toErrorDev( 'Warning: Unknown event handler property `on-unknown`. It will be ignored.\n in div (at **)', ); diff --git a/packages/react-dom/src/__tests__/ReactDOMComponentTree-test.js b/packages/react-dom/src/__tests__/ReactDOMComponentTree-test.js index b00bd145ae148..e27c3b5b660b9 100644 --- a/packages/react-dom/src/__tests__/ReactDOMComponentTree-test.js +++ b/packages/react-dom/src/__tests__/ReactDOMComponentTree-test.js @@ -190,7 +190,9 @@ describe('ReactDOMComponentTree', () => { it('finds instance of node that is attempted to be unmounted', () => { const component =
    ; const node = ReactDOM.render(
    {component}
    , container); - expect(() => ReactDOM.unmountComponentAtNode(node)).toErrorDev( + expect(() => + ReactDOM.unmountComponentAtNode(node), + ).toErrorDev( "unmountComponentAtNode(): The node you're attempting to unmount " + 'was rendered by React and is not a top-level container. You may ' + 'have accidentally passed in a React root node instead of its ' + @@ -207,7 +209,9 @@ describe('ReactDOMComponentTree', () => { ); const anotherComponent =
    ; const instance = ReactDOM.render(component, container); - expect(() => ReactDOM.render(anotherComponent, instance)).toErrorDev( + expect(() => + ReactDOM.render(anotherComponent, instance), + ).toErrorDev( 'render(...): Replacing React-rendered children with a new root ' + 'component. If you intended to update the children of this node, ' + 'you should instead have the existing children update their state ' + diff --git a/packages/react-dom/src/__tests__/ReactDOMFiber-test.js b/packages/react-dom/src/__tests__/ReactDOMFiber-test.js index 59d9b5a1fc381..a9856cc3f0c80 100644 --- a/packages/react-dom/src/__tests__/ReactDOMFiber-test.js +++ b/packages/react-dom/src/__tests__/ReactDOMFiber-test.js @@ -1151,7 +1151,9 @@ describe('ReactDOMFiber', () => { expect(container.innerHTML).toBe('
    bar
    '); // then we mess with the DOM before an update container.innerHTML = '
    MEOW.
    '; - expect(() => ReactDOM.render(
    baz
    , container)).toErrorDev( + expect(() => + ReactDOM.render(
    baz
    , container), + ).toErrorDev( 'render(...): ' + 'It looks like the React-rendered content of this container was ' + 'removed without using React. This is not supported and will ' + @@ -1168,7 +1170,9 @@ describe('ReactDOMFiber', () => { expect(container.innerHTML).toBe('
    bar
    '); // then we mess with the DOM before an update container.innerHTML = ''; - expect(() => ReactDOM.render(
    baz
    , container)).toErrorDev( + expect(() => + ReactDOM.render(
    baz
    , container), + ).toErrorDev( 'render(...): ' + 'It looks like the React-rendered content of this container was ' + 'removed without using React. This is not supported and will ' + diff --git a/packages/react-dom/src/__tests__/ReactDOMFiberAsync-test.internal.js b/packages/react-dom/src/__tests__/ReactDOMFiberAsync-test.internal.js index 15515672747a6..8cf28cc6adf41 100644 --- a/packages/react-dom/src/__tests__/ReactDOMFiberAsync-test.internal.js +++ b/packages/react-dom/src/__tests__/ReactDOMFiberAsync-test.internal.js @@ -593,14 +593,11 @@ describe('ReactDOMFiberAsync', () => { function App({label}) { const [step, setStep] = useState(0); - useEffect( - () => { - if (step < 3) { - setStep(step + 1); - } - }, - [step], - ); + useEffect(() => { + if (step < 3) { + setStep(step + 1); + } + }, [step]); // The component should keep re-rendering itself until `step` is 3. return step === 3 ? 'Finished' : 'Unresolved'; diff --git a/packages/react-dom/src/__tests__/ReactDOMServerIntegrationAttributes-test.js b/packages/react-dom/src/__tests__/ReactDOMServerIntegrationAttributes-test.js index f785addd4485f..87673b0e2cf4e 100644 --- a/packages/react-dom/src/__tests__/ReactDOMServerIntegrationAttributes-test.js +++ b/packages/react-dom/src/__tests__/ReactDOMServerIntegrationAttributes-test.js @@ -636,10 +636,7 @@ describe('ReactDOMServerIntegration', () => { }); itRenders('no unknown events', async render => { - const e = await render( -
    , - 1, - ); + const e = await render(
    , 1); expect(e.getAttribute('onunknownevent')).toBe(null); }); diff --git a/packages/react-dom/src/__tests__/ReactDOMServerIntegrationElements-test.js b/packages/react-dom/src/__tests__/ReactDOMServerIntegrationElements-test.js index 9c98f10cb2c1f..5d56419a1a114 100644 --- a/packages/react-dom/src/__tests__/ReactDOMServerIntegrationElements-test.js +++ b/packages/react-dom/src/__tests__/ReactDOMServerIntegrationElements-test.js @@ -258,8 +258,7 @@ describe('ReactDOMServerIntegration', () => {
    {[['a'], 'b']}
    - - d + d
    e
    , @@ -493,11 +492,13 @@ describe('ReactDOMServerIntegration', () => { // Put dangerouslySetInnerHTML one level deeper because otherwise // hydrating from a bad markup would cause a mismatch (since we don't // patch dangerouslySetInnerHTML as text content). - const e = (await render( -
    - -
    , - )).firstChild; + const e = ( + await render( +
    + +
    , + ) + ).firstChild; expect(e.childNodes.length).toBe(1); expect(e.firstChild.nodeType).toBe(TEXT_NODE_TYPE); expect(e.textContent).toBe('0'); @@ -507,11 +508,13 @@ describe('ReactDOMServerIntegration', () => { // Put dangerouslySetInnerHTML one level deeper because otherwise // hydrating from a bad markup would cause a mismatch (since we don't // patch dangerouslySetInnerHTML as text content). - const e = (await render( -
    - -
    , - )).firstChild; + const e = ( + await render( +
    + +
    , + ) + ).firstChild; expect(e.childNodes.length).toBe(1); expect(e.firstChild.nodeType).toBe(TEXT_NODE_TYPE); expect(e.firstChild.data).toBe('false'); @@ -523,11 +526,13 @@ describe('ReactDOMServerIntegration', () => { // Put dangerouslySetInnerHTML one level deeper because otherwise // hydrating from a bad markup would cause a mismatch (since we don't // patch dangerouslySetInnerHTML as text content). - const e = (await render( -
    - -
    , - )).firstChild; + const e = ( + await render( +
    + +
    , + ) + ).firstChild; expect(e.childNodes.length).toBe(1); expect(e.firstChild.nodeType).toBe(TEXT_NODE_TYPE); expect(e.textContent).toBe('hello'); diff --git a/packages/react-dom/src/__tests__/ReactDOMServerIntegrationHooks-test.internal.js b/packages/react-dom/src/__tests__/ReactDOMServerIntegrationHooks-test.internal.js index b4f99453cd328..a4e638cc006ee 100644 --- a/packages/react-dom/src/__tests__/ReactDOMServerIntegrationHooks-test.internal.js +++ b/packages/react-dom/src/__tests__/ReactDOMServerIntegrationHooks-test.internal.js @@ -322,13 +322,10 @@ describe('ReactDOMServerHooks', () => { itRenders('basic render', async render => { function CapitalizedText(props) { const text = props.text; - const capitalizedText = useMemo( - () => { - yieldValue(`Capitalize '${text}'`); - return text.toUpperCase(); - }, - [text], - ); + const capitalizedText = useMemo(() => { + yieldValue(`Capitalize '${text}'`); + return text.toUpperCase(); + }, [text]); return ; } @@ -360,13 +357,10 @@ describe('ReactDOMServerHooks', () => { async render => { function CapitalizedText(props) { const [text, setText] = useState(props.text); - const capitalizedText = useMemo( - () => { - yieldValue(`Capitalize '${text}'`); - return text.toUpperCase(); - }, - [text], - ); + const capitalizedText = useMemo(() => { + yieldValue(`Capitalize '${text}'`); + return text.toUpperCase(); + }, [text]); if (text === 'hello') { setText('hello, world.'); @@ -391,13 +385,10 @@ describe('ReactDOMServerHooks', () => { function CapitalizedText(props) { const [text, setText] = useState(props.text); const [count, setCount] = useState(0); - const capitalizedText = useMemo( - () => { - yieldValue(`Capitalize '${text}'`); - return text.toUpperCase(); - }, - [text], - ); + const capitalizedText = useMemo(() => { + yieldValue(`Capitalize '${text}'`); + return text.toUpperCase(); + }, [text]); yieldValue(count); diff --git a/packages/react-dom/src/__tests__/ReactDOMSuspensePlaceholder-test.js b/packages/react-dom/src/__tests__/ReactDOMSuspensePlaceholder-test.js index 7f1d1c5db0729..94bd63ff026cd 100644 --- a/packages/react-dom/src/__tests__/ReactDOMSuspensePlaceholder-test.js +++ b/packages/react-dom/src/__tests__/ReactDOMSuspensePlaceholder-test.js @@ -33,13 +33,16 @@ describe('ReactDOMSuspensePlaceholder', () => { container = document.createElement('div'); document.body.appendChild(container); - TextResource = ReactCache.unstable_createResource(([text, ms = 0]) => { - return new Promise((resolve, reject) => - setTimeout(() => { - resolve(text); - }, ms), - ); - }, ([text, ms]) => text); + TextResource = ReactCache.unstable_createResource( + ([text, ms = 0]) => { + return new Promise((resolve, reject) => + setTimeout(() => { + resolve(text); + }, ms), + ); + }, + ([text, ms]) => text, + ); }); afterEach(() => { diff --git a/packages/react-dom/src/__tests__/ReactFunctionComponent-test.js b/packages/react-dom/src/__tests__/ReactFunctionComponent-test.js index ff9c87be60390..2b33321358ffd 100644 --- a/packages/react-dom/src/__tests__/ReactFunctionComponent-test.js +++ b/packages/react-dom/src/__tests__/ReactFunctionComponent-test.js @@ -163,11 +163,11 @@ describe('ReactFunctionComponent', () => { : // It happens because we don't save _owner in production for // function components. 'Element ref was specified as a string (me) but no owner was set. This could happen for one of' + - ' the following reasons:\n' + - '1. You may be adding a ref to a function component\n' + - "2. You may be adding a ref to a component that was not created inside a component's render method\n" + - '3. You have multiple copies of React loaded\n' + - 'See https://fb.me/react-refs-must-have-owner for more information.', + ' the following reasons:\n' + + '1. You may be adding a ref to a function component\n' + + "2. You may be adding a ref to a component that was not created inside a component's render method\n" + + '3. You have multiple copies of React loaded\n' + + 'See https://fb.me/react-refs-must-have-owner for more information.', ); }); diff --git a/packages/react-dom/src/__tests__/ReactMount-test.js b/packages/react-dom/src/__tests__/ReactMount-test.js index 600a085260a7e..8d1b03cb4b4fd 100644 --- a/packages/react-dom/src/__tests__/ReactMount-test.js +++ b/packages/react-dom/src/__tests__/ReactMount-test.js @@ -59,7 +59,9 @@ describe('ReactMount', () => { } } - expect(() => ReactTestUtils.renderIntoDocument(Component)).toErrorDev( + expect(() => + ReactTestUtils.renderIntoDocument(Component), + ).toErrorDev( 'Functions are not valid as a React child. ' + 'This may happen if you return a Component instead of from render. ' + 'Or maybe you meant to call this function rather than return it.', @@ -125,7 +127,9 @@ describe('ReactMount', () => { const container = document.createElement('container'); container.innerHTML = ReactDOMServer.renderToString(
    ) + ' '; - expect(() => ReactDOM.hydrate(
    , container)).toErrorDev( + expect(() => + ReactDOM.hydrate(
    , container), + ).toErrorDev( 'Did not expect server HTML to contain the text node " " in .', {withoutStack: true}, ); @@ -195,7 +199,9 @@ describe('ReactMount', () => { // Test that blasting away children throws a warning const rootNode = container.firstChild; - expect(() => ReactDOM.render(, rootNode)).toErrorDev( + expect(() => + ReactDOM.render(, rootNode), + ).toErrorDev( 'Warning: render(...): Replacing React-rendered children with a new ' + 'root component. If you intended to update the children of this node, ' + 'you should instead have the existing children update their state and ' + @@ -223,7 +229,9 @@ describe('ReactMount', () => { // Make sure ReactDOM and ReactDOMOther are different copies expect(ReactDOM).not.toEqual(ReactDOMOther); - expect(() => ReactDOMOther.unmountComponentAtNode(container)).toErrorDev( + expect(() => + ReactDOMOther.unmountComponentAtNode(container), + ).toErrorDev( "Warning: unmountComponentAtNode(): The node you're attempting to unmount " + 'was rendered by another copy of React.', {withoutStack: true}, diff --git a/packages/react-dom/src/__tests__/ReactMountDestruction-test.js b/packages/react-dom/src/__tests__/ReactMountDestruction-test.js index 360a6802d9451..ed65c4cbfa7eb 100644 --- a/packages/react-dom/src/__tests__/ReactMountDestruction-test.js +++ b/packages/react-dom/src/__tests__/ReactMountDestruction-test.js @@ -50,7 +50,9 @@ describe('ReactMount', () => { // Test that unmounting at a root node gives a helpful warning const rootDiv = mainContainerDiv.firstChild; - expect(() => ReactDOM.unmountComponentAtNode(rootDiv)).toErrorDev( + expect(() => + ReactDOM.unmountComponentAtNode(rootDiv), + ).toErrorDev( "Warning: unmountComponentAtNode(): The node you're attempting to " + 'unmount was rendered by React and is not a top-level container. You ' + 'may have accidentally passed in a React root node instead of its ' + @@ -73,7 +75,9 @@ describe('ReactMount', () => { // Test that unmounting at a non-root node gives a different warning const nonRootDiv = mainContainerDiv.firstChild.firstChild; - expect(() => ReactDOM.unmountComponentAtNode(nonRootDiv)).toErrorDev( + expect(() => + ReactDOM.unmountComponentAtNode(nonRootDiv), + ).toErrorDev( "Warning: unmountComponentAtNode(): The node you're attempting to " + 'unmount was rendered by React and is not a top-level container. ' + 'Instead, have the parent component update its state and rerender in ' + diff --git a/packages/react-dom/src/__tests__/ReactMultiChild-test.js b/packages/react-dom/src/__tests__/ReactMultiChild-test.js index 12b845ef139cd..6eb0199be9c8e 100644 --- a/packages/react-dom/src/__tests__/ReactMultiChild-test.js +++ b/packages/react-dom/src/__tests__/ReactMultiChild-test.js @@ -281,7 +281,16 @@ describe('ReactMultiChild', () => { it('should warn for using maps as children with owner info', () => { class Parent extends React.Component { render() { - return
    {new Map([['foo', 0], ['bar', 1]])}
    ; + return ( +
    + { + new Map([ + ['foo', 0], + ['bar', 1], + ]) + } +
    + ); } } const container = document.createElement('div'); @@ -296,8 +305,8 @@ describe('ReactMultiChild', () => { it('should warn for using generators as children', () => { function* Foo() { - yield

    Hello

    ; - yield

    World

    ; + yield (

    Hello

    ); + yield (

    World

    ); } const div = document.createElement('div'); @@ -318,8 +327,8 @@ describe('ReactMultiChild', () => { it('should not warn for using generators in legacy iterables', () => { const fooIterable = { '@@iterator': function*() { - yield

    Hello

    ; - yield

    World

    ; + yield (

    Hello

    ); + yield (

    World

    ); }, }; @@ -338,8 +347,8 @@ describe('ReactMultiChild', () => { it('should not warn for using generators in modern iterables', () => { const fooIterable = { [Symbol.iterator]: function*() { - yield

    Hello

    ; - yield

    World

    ; + yield (

    Hello

    ); + yield (

    World

    ); }, }; @@ -374,7 +383,13 @@ describe('ReactMultiChild', () => { class Letters extends React.Component { render() { const letters = this.props.letters.split(''); - return
    {letters.map(c => )}
    ; + return ( +
    + {letters.map(c => ( + + ))} +
    + ); } } diff --git a/packages/react-dom/src/__tests__/ReactRenderDocument-test.js b/packages/react-dom/src/__tests__/ReactRenderDocument-test.js index a85d86475679c..97ff0393f8741 100644 --- a/packages/react-dom/src/__tests__/ReactRenderDocument-test.js +++ b/packages/react-dom/src/__tests__/ReactRenderDocument-test.js @@ -35,7 +35,9 @@ describe('rendering React components at document', () => { describe('with old implicit hydration API', () => { function expectDeprecationWarningWithFiber(callback) { - expect(callback).toWarnDev( + expect( + callback, + ).toWarnDev( 'render(): Calling ReactDOM.render() to hydrate server-rendered markup ' + 'will stop working in React v17. Replace the ReactDOM.render() call ' + 'with ReactDOM.hydrate() if you want React to attach to the server HTML.', diff --git a/packages/react-dom/src/__tests__/ReactServerRendering-test.js b/packages/react-dom/src/__tests__/ReactServerRendering-test.js index e68de160575cb..bcefcdb652468 100644 --- a/packages/react-dom/src/__tests__/ReactServerRendering-test.js +++ b/packages/react-dom/src/__tests__/ReactServerRendering-test.js @@ -644,7 +644,9 @@ describe('ReactDOMServer', () => { } ReactDOMServer.renderToString(); - expect(() => jest.runOnlyPendingTimers()).toErrorDev( + expect(() => + jest.runOnlyPendingTimers(), + ).toErrorDev( 'Warning: setState(...): Can only update a mounting component.' + ' This usually means you called setState() outside componentWillMount() on the server.' + ' This is a no-op.\n\nPlease check the code for the Foo component.', @@ -672,7 +674,9 @@ describe('ReactDOMServer', () => { } ReactDOMServer.renderToString(); - expect(() => jest.runOnlyPendingTimers()).toErrorDev( + expect(() => + jest.runOnlyPendingTimers(), + ).toErrorDev( 'Warning: forceUpdate(...): Can only update a mounting component. ' + 'This usually means you called forceUpdate() outside componentWillMount() on the server. ' + 'This is a no-op.\n\nPlease check the code for the Baz component.', diff --git a/packages/react-dom/src/__tests__/ReactTestUtils-test.js b/packages/react-dom/src/__tests__/ReactTestUtils-test.js index 829010d97823a..540f23edd17c0 100644 --- a/packages/react-dom/src/__tests__/ReactTestUtils-test.js +++ b/packages/react-dom/src/__tests__/ReactTestUtils-test.js @@ -53,7 +53,9 @@ describe('ReactTestUtils', () => { MockedComponent.prototype.render = jest.fn(); // Patch it up so it returns its children. - expect(() => ReactTestUtils.mockComponent(MockedComponent)).toWarnDev( + expect(() => + ReactTestUtils.mockComponent(MockedComponent), + ).toWarnDev( 'ReactTestUtils.mockComponent() is deprecated. ' + 'Use shallow rendering or jest.mock() instead.\n\n' + 'See https://fb.me/test-utils-mock-component for more information.', diff --git a/packages/react-dom/src/__tests__/ReactTestUtilsAct-test.js b/packages/react-dom/src/__tests__/ReactTestUtilsAct-test.js index 7b380a0b82d79..d68a4a1141709 100644 --- a/packages/react-dom/src/__tests__/ReactTestUtilsAct-test.js +++ b/packages/react-dom/src/__tests__/ReactTestUtilsAct-test.js @@ -337,12 +337,9 @@ function runActTests(label, render, unmount, rerender) { await null; setState(x => x + 1); } - React.useEffect( - () => { - ticker(); - }, - [Math.min(state, 4)], - ); + React.useEffect(() => { + ticker(); + }, [Math.min(state, 4)]); return state; } @@ -521,13 +518,10 @@ function runActTests(label, render, unmount, rerender) { await null; setState(x => x + 1); } - React.useEffect( - () => { - Scheduler.unstable_yieldValue(state); - ticker(); - }, - [Math.min(state, 4)], - ); + React.useEffect(() => { + Scheduler.unstable_yieldValue(state); + ticker(); + }, [Math.min(state, 4)]); return state; } diff --git a/packages/react-dom/src/__tests__/ReactTestUtilsActUnmockedScheduler-test.js b/packages/react-dom/src/__tests__/ReactTestUtilsActUnmockedScheduler-test.js index baa4f63e4ba75..3017096d30bfd 100644 --- a/packages/react-dom/src/__tests__/ReactTestUtilsActUnmockedScheduler-test.js +++ b/packages/react-dom/src/__tests__/ReactTestUtilsActUnmockedScheduler-test.js @@ -147,13 +147,10 @@ it('can handle cascading promises', async () => { await null; setState(x => x + 1); } - React.useEffect( - () => { - yields.push(state); - ticker(); - }, - [Math.min(state, 4)], - ); + React.useEffect(() => { + yields.push(state); + ticker(); + }, [Math.min(state, 4)]); return state; } diff --git a/packages/react-dom/src/__tests__/renderSubtreeIntoContainer-test.js b/packages/react-dom/src/__tests__/renderSubtreeIntoContainer-test.js index 881c7b15d7945..c5ad79e2eba8f 100644 --- a/packages/react-dom/src/__tests__/renderSubtreeIntoContainer-test.js +++ b/packages/react-dom/src/__tests__/renderSubtreeIntoContainer-test.js @@ -312,11 +312,11 @@ describe('renderSubtreeIntoContainer', () => { }).toThrow( __DEV__ ? '_processChildContext is not available in React 16+. This likely ' + - 'means you have multiple copies of React and are attempting to nest ' + - 'a React 15 tree inside a React 16 tree using ' + - "unstable_renderSubtreeIntoContainer, which isn't supported. Try to " + - 'make sure you have only one copy of React (and ideally, switch to ' + - 'ReactDOM.createPortal).' + 'means you have multiple copies of React and are attempting to nest ' + + 'a React 15 tree inside a React 16 tree using ' + + "unstable_renderSubtreeIntoContainer, which isn't supported. Try to " + + 'make sure you have only one copy of React (and ideally, switch to ' + + 'ReactDOM.createPortal).' : "Cannot read property '_processChildContext' of undefined", ); }); diff --git a/packages/react-dom/src/client/ReactDOMLegacy.js b/packages/react-dom/src/client/ReactDOMLegacy.js index aca2a7a7adbfa..3da5e468c2679 100644 --- a/packages/react-dom/src/client/ReactDOMLegacy.js +++ b/packages/react-dom/src/client/ReactDOMLegacy.js @@ -385,9 +385,9 @@ export function unmountComponentAtNode(container: DOMContainer) { 'was rendered by React and is not a top-level container. %s', isContainerReactRoot ? 'You may have accidentally passed in a React root node instead ' + - 'of its container.' + 'of its container.' : 'Instead, have the parent component update its state and ' + - 'rerender in order to remove this component.', + 'rerender in order to remove this component.', ); } } diff --git a/packages/react-dom/src/events/SelectEventPlugin.js b/packages/react-dom/src/events/SelectEventPlugin.js index cd1c1a436ac7e..b358e896eaf37 100644 --- a/packages/react-dom/src/events/SelectEventPlugin.js +++ b/packages/react-dom/src/events/SelectEventPlugin.js @@ -94,8 +94,8 @@ function getEventTargetDocument(eventTarget) { return eventTarget.window === eventTarget ? eventTarget.document : eventTarget.nodeType === DOCUMENT_NODE - ? eventTarget - : eventTarget.ownerDocument; + ? eventTarget + : eventTarget.ownerDocument; } /** diff --git a/packages/react-dom/src/events/SyntheticWheelEvent.js b/packages/react-dom/src/events/SyntheticWheelEvent.js index 7c6a1d1f4eef1..e8e152d3414c1 100644 --- a/packages/react-dom/src/events/SyntheticWheelEvent.js +++ b/packages/react-dom/src/events/SyntheticWheelEvent.js @@ -16,20 +16,20 @@ const SyntheticWheelEvent = SyntheticMouseEvent.extend({ return 'deltaX' in event ? event.deltaX : // Fallback to `wheelDeltaX` for Webkit and normalize (right is positive). - 'wheelDeltaX' in event - ? -event.wheelDeltaX - : 0; + 'wheelDeltaX' in event + ? -event.wheelDeltaX + : 0; }, deltaY(event) { return 'deltaY' in event ? event.deltaY : // Fallback to `wheelDeltaY` for Webkit and normalize (down is positive). - 'wheelDeltaY' in event - ? -event.wheelDeltaY - : // Fallback to `wheelDelta` for IE<9 and normalize (down is positive). - 'wheelDelta' in event - ? -event.wheelDelta - : 0; + 'wheelDeltaY' in event + ? -event.wheelDeltaY + : // Fallback to `wheelDelta` for IE<9 and normalize (down is positive). + 'wheelDelta' in event + ? -event.wheelDelta + : 0; }, deltaZ: null, diff --git a/packages/react-dom/src/events/__tests__/SimpleEventPlugin-test.internal.js b/packages/react-dom/src/events/__tests__/SimpleEventPlugin-test.internal.js index 5ddf53fb3344f..43d2ad44397c1 100644 --- a/packages/react-dom/src/events/__tests__/SimpleEventPlugin-test.internal.js +++ b/packages/react-dom/src/events/__tests__/SimpleEventPlugin-test.internal.js @@ -388,9 +388,7 @@ describe('SimpleEventPlugin', function() { class Button extends React.Component { state = {lowPriCount: 0}; render() { - const text = `High-pri count: ${ - this.props.highPriCount - }, Low-pri count: ${this.state.lowPriCount}`; + const text = `High-pri count: ${this.props.highPriCount}, Low-pri count: ${this.state.lowPriCount}`; Scheduler.unstable_yieldValue(text); return (