Question:
<!-- Please provide a clear and concise description of what the bug is. Include screenshots if needed. Please test using the latest version of the relevant React packages to make sure your issue has not already been fixed. --React version: DevTools version 4.12.2- from within a React component where the last argument is typeof <!-- Your bug will get fixed much faster if we can run your code and it doesn't have dependencies other than React. Issues without reproduction steps or code examples may be immediately closed as not actionable. --Link to code example: The bug only happens when you make a change, so if you use the code sandbox link you need, open a new window, active dev tools, open the React dev tools and then uncomment line 5: only then will the error actually happen. I've located the culprit to this line of code And would offer the following change <!-- Please provide a CodeSandbox (), a link to a repository on GitHub, or provide a minimal code example that reproduces the problem. You may provide a screenshot of the application if you think it is relevant to your bug report. Here are some tips for providing a minimal example: --React DevTools is implicitly converting a Symbol to a string. React DevTools does not implicitly try to convert a Symbol to a string.
Thanks for the report. Also reproduced with DevTools version 4.12.3- in Chrome 90 In addition to fixing the bug, it would also be nice to guard against devtools failing so that the UI is unaffected if devtools is faulty. /cc
Your the best, thanks for a quick turn around!

'n    in Child (at **)n    in Intermediate (at **)n    in Parent (at **)', ); }); <ins> it('should correctly log Symbols', () => { const Component = ({children}) => { fakeConsole.warn('Symbol:', Symbol('')); return null; }; act(() => ReactDOM.render(<Component />, document.createElement('div'))); expect(mockWarn).toHaveBeenCalledTimes(1); expect(mockWarn.mock.calls[0][0]).toBe('Symbol:'); }); </ins> });

if (consoleSettingsRef.appendComponentStack) { const lastArg = args.length > 0 ? args[args.length - 1] : null; const alreadyHasComponentStack = <del> lastArg !== null && isStringComponentStack(lastArg); </del> <ins> typeof lastArg === 'string' && isStringComponentStack(lastArg); </ins> // If we are ever called with a string that already has a component stack, // e.g. a React error/warning, don't append a second stack.

return [<div />]; } <ins> function ComponentWithSymbolWarning() { console.warn('this is a symbol', Symbol('foo')); console.error('this is a symbol', Symbol.for('bar')); return null; } </ins> export default function ErrorsAndWarnings() { const [count, setCount] = useState(0); const handleClick = () => setCount(count + 1);

<ReallyLongErrorMessageThatWillCauseTextToBeTruncated /> <DuplicateWarningsAndErrors /> <MultipleWarningsAndErrors /> <ins> <ComponentWithSymbolWarning /> </ins> </Fragment> ); }


Question:
A very small thing, would it be better to change the to in the error log since we separated the original logic into two functions (, )? Although it wouldn't be an issue for the authors, it feels like it would be better to sync it with the function name? Would you mind renaming it in the next 'typo fixing'?
Thanks!

if (__DEV__) { if (typeof (type: any).tag === 'number') { console.error( <del> 'Received an unexpected object in getComponentName(). ' + </del> <ins> 'Received an unexpected object in getComponentNameFromType(). ' + </ins> 'This is likely a bug in React. Please file an issue.', ); }


Question: This function will throw this error if one of the arguments is type of . The error is swallowed but it does interfere with debugging. When I run with the "pause on caught exceptions" I get trapped here all the time. Can we change into ??? Every time No response 13.2- TypeError: Cannot convert a Symbol value to a string No response No response No response

getDisplayName, getDisplayNameForReactElement, } from 'react-devtools-shared/src/utils'; <ins> import {format} from 'react-devtools-shared/src/backend/utils'; </ins> import { REACT_SUSPENSE_LIST_TYPE as SuspenseList, REACT_STRICT_MODE_TYPE as StrictMode,

expect(getDisplayName(FauxComponent, 'Fallback')).toEqual('Fallback'); }); }); describe('getDisplayNameForReactElement', () => { it('should return correct display name for an element with function type', () => { function FauxComponent() {}

'OverrideDisplayName', ); }); it('should return correct display name for an element with a type of StrictMode', () => { const element = createElement(StrictMode); expect(getDisplayNameForReactElement(element)).toEqual('StrictMode'); }); it('should return correct display name for an element with a type of SuspenseList', () => { const element = createElement(SuspenseList); expect(getDisplayNameForReactElement(element)).toEqual('SuspenseList'); }); it('should return NotImplementedInDevtools for an element with invalid symbol type', () => { const element = createElement(Symbol('foo')); expect(getDisplayNameForReactElement(element)).toEqual( 'NotImplementedInDevtools', ); }); it('should return NotImplementedInDevtools for an element with invalid type', () => { const element = createElement(true); expect(getDisplayNameForReactElement(element)).toEqual( 'NotImplementedInDevtools', ); }); it('should return Element for null type', () => { const element = createElement(); expect(getDisplayNameForReactElement(element)).toEqual('Element'); }); }); <ins> describe('format', () => { it('should format simple strings', () => { expect(format('a', 'b', 'c')).toEqual('a b c'); }); it('should format multiple argument types', () => { expect(format('abc', 123, true)).toEqual('abc 123 true'); }); it('should support string substitutions', () => { expect(format('a %s b %s c', 123, true)).toEqual('a 123 b true c'); }); it('should gracefully handle Symbol types', () => { expect(format(Symbol('a'), 'b', Symbol('c'))).toEqual( 'Symbol(a) b Symbol(c)', ); }); it('should gracefully handle Symbol type for the first argument', () => { expect(format(Symbol('abc'), 123)).toEqual('Symbol(abc) 123'); }); }); </ins> });

maybeMessage: any, ...inputArgs: $ReadOnlyArray<any> ): string { <del> if (typeof maybeMessage !== 'string') { return [maybeMessage, ...inputArgs].join(' '); } const re = /(%?)(%([jds]))/g; </del> const args = inputArgs.slice(); <del> let formatted: string = maybeMessage; if (args.length) { formatted = formatted.replace(re, (match, escaped, ptn, flag) => { let arg = args.shift(); switch (flag) { case 's': arg += ''; break; case 'd': case 'i': arg = parseInt(arg, 10).toString(); break; case 'f': arg = parseFloat(arg).toString(); break; } if (!escaped) { return arg; } args.unshift(arg); return match; }); </del> <ins> // Symbols cannot be concatenated with Strings. let formatted: string = typeof maybeMessage === 'symbol' ? maybeMessage.toString() : '' + maybeMessage; // If the first argument is a string, check for substitutions. if (typeof maybeMessage === 'string') { if (args.length) { const REGEXP = /(%?)(%([jds]))/g; formatted = formatted.replace(REGEXP, (match, escaped, ptn, flag) => { let arg = args.shift(); switch (flag) { case 's': arg += ''; break; case 'd': case 'i': arg = parseInt(arg, 10).toString(); break; case 'f': arg = parseFloat(arg).toString(); break; } if (!escaped) { return arg; } args.unshift(arg); return match; }); } </ins> } <del> // arguments remain after formatting </del> <ins> // Arguments that remain after formatting. </ins> if (args.length) { <del> formatted += ' ' + args.join(' '); </del> <ins> for (let i = 0; i < args.length; i++) { const arg = args[i]; // Symbols cannot be concatenated with Strings. formatted += ' ' + (typeof arg === 'symbol' ? arg.toString() : arg); } </ins> } <del> // update escaped %% values </del> <ins> // Update escaped %% values. </ins> formatted = formatted.replace(/%{2,2}/g, '%'); return '' + formatted;


Question:
the block to inspect "Component" in DevTools : "Could not inspect element with id 5" Originally reported in https://user- Every time
Here's another Chrome extension build with the fix from :
Everything fixed. Awesome :+1:
FYI just published as 4.13.4

}); describe('inline errors and warnings', () => { <del> // Some actions require the Fiber id. // In those instances you might want to make assertions based on the ID instead of the index. function getErrorsAndWarningsForElement(id: number) { const index = ((store.getIndexOfElementID(id): any): number); return getErrorsAndWarningsForElementAtIndex(index); } </del> async function getErrorsAndWarningsForElementAtIndex(index) { const id = ((store.getElementIDAtIndex(index): any): number); <ins> if (id == null) { throw Error(`Element at index "${index}"" not found in store`); } </ins> let errors = null; let warnings = null;

jest.runOnlyPendingTimers(); let data = [ <del> await getErrorsAndWarningsForElement(1), await getErrorsAndWarningsForElement(2), </del> <ins> await getErrorsAndWarningsForElementAtIndex(0), await getErrorsAndWarningsForElementAtIndex(1), </ins> ]; expect(data).toMatchInlineSnapshot(` Array [

jest.runOnlyPendingTimers(); data = [ <del> await getErrorsAndWarningsForElement(1), await getErrorsAndWarningsForElement(2), </del> <ins> await getErrorsAndWarningsForElementAtIndex(0), await getErrorsAndWarningsForElementAtIndex(1), </ins> ]; expect(data).toMatchInlineSnapshot(` Array [

typeof setSuspenseHandler === 'function' && typeof scheduleUpdate === 'function'; <del> // Set of Fibers (IDs) with recently changed number of error/warning messages. const fibersWithChangedErrorOrWarningCounts: Set<number> = new Set(); </del> <ins> // Tracks Fibers with recently changed number of error/warning messages. // These collections store the Fiber rather than the ID, // in order to avoid generating an ID for Fibers that never get mounted // (due to e.g. Suspense or error boundaries). // onErrorOrWarning() adds Fibers and recordPendingErrorsAndWarnings() later clears them. const fibersWithChangedErrorOrWarningCounts: Set<Fiber> = new Set(); const pendingFiberToErrorsMap: Map<Fiber, Map<string, number>> = new Map(); const pendingFiberToWarningsMap: Map<Fiber, Map<string, number>> = new Map(); </ins> // Mapping of fiber IDs to error/warning messages and counts. <del> const fiberToErrorsMap: Map<number, Map<string, number>> = new Map(); const fiberToWarningsMap: Map<number, Map<string, number>> = new Map(); </del> <ins> const fiberIDToErrorsMap: Map<number, Map<string, number>> = new Map(); const fiberIDToWarningsMap: Map<number, Map<string, number>> = new Map(); </ins> function clearErrorsAndWarnings() { // eslint-disable-next-line no-for-of-loops/no-for-of-loops <del> for (const id of fiberToErrorsMap.keys()) { fibersWithChangedErrorOrWarningCounts.add(id); updateMostRecentlyInspectedElementIfNecessary(id); </del> <ins> for (const id of fiberIDToErrorsMap.keys()) { const fiber = idToArbitraryFiberMap.get(id); if (fiber != null) { fibersWithChangedErrorOrWarningCounts.add(fiber); updateMostRecentlyInspectedElementIfNecessary(id); } </ins> } // eslint-disable-next-line no-for-of-loops/no-for-of-loops <del> for (const id of fiberToWarningsMap.keys()) { fibersWithChangedErrorOrWarningCounts.add(id); updateMostRecentlyInspectedElementIfNecessary(id); </del> <ins> for (const id of fiberIDToWarningsMap.keys()) { const fiber = idToArbitraryFiberMap.get(id); if (fiber != null) { fibersWithChangedErrorOrWarningCounts.add(fiber); updateMostRecentlyInspectedElementIfNecessary(id); } </ins> } <del> fiberToErrorsMap.clear(); fiberToWarningsMap.clear(); </del> <ins> fiberIDToErrorsMap.clear(); fiberIDToWarningsMap.clear(); </ins> flushPendingEvents(); } <del> function clearErrorsForFiberID(id: number) { if (fiberToErrorsMap.has(id)) { fiberToErrorsMap.delete(id); fibersWithChangedErrorOrWarningCounts.add(id); flushPendingEvents(); } </del> <ins> function clearMessageCountHelper( fiberID: number, pendingFiberToMessageCountMap: Map<Fiber, Map<string, number>>, fiberIDToMessageCountMap: Map<number, Map<string, number>>, ) { const fiber = idToArbitraryFiberMap.get(fiberID); if (fiber != null) { // Throw out any pending changes. pendingFiberToErrorsMap.delete(fiber); </ins> <del> updateMostRecentlyInspectedElementIfNecessary(id); } </del> <ins> if (fiberIDToMessageCountMap.has(fiberID)) { fiberIDToMessageCountMap.delete(fiberID); // If previous flushed counts have changed, schedule an update too. fibersWithChangedErrorOrWarningCounts.add(fiber); flushPendingEvents(); </ins> <del> function clearWarningsForFiberID(id: number) { if (fiberToWarningsMap.has(id)) { fiberToWarningsMap.delete(id); fibersWithChangedErrorOrWarningCounts.add(id); flushPendingEvents(); </del> <ins> updateMostRecentlyInspectedElementIfNecessary(fiberID); } else { fibersWithChangedErrorOrWarningCounts.delete(fiber); } </ins> } <ins> } </ins> <del> updateMostRecentlyInspectedElementIfNecessary(id); </del> <ins> function clearErrorsForFiberID(fiberID: number) { clearMessageCountHelper( fiberID, pendingFiberToErrorsMap, fiberIDToErrorsMap, ); } function clearWarningsForFiberID(fiberID: number) { clearMessageCountHelper( fiberID, pendingFiberToWarningsMap, fiberIDToWarningsMap, ); </ins> } function updateMostRecentlyInspectedElementIfNecessary(

args: $ReadOnlyArray<any>, ): void { const message = format(...args); <del> // Note that by calling these functions we may be creating the ID for the first time. // If the Fiber is then never mounted, we are responsible for cleaning up after ourselves. // This is important because getOrGenerateFiberID() stores a Fiber in a couple of local Maps. // If the Fiber never mounts and we don't clean up after this code, we could leak. // Fortunately we would only leak Fibers that have errors/warnings associated with them, // which is hopefully only a small set and only in DEV mode– but this is still not great. // We should clean up Fibers like this when flushing; see recordPendingErrorsAndWarnings(). const fiberID = getOrGenerateFiberID(fiber); </del> if (__DEBUG__) { debug('onErrorOrWarning', fiber, null, `${type}: "${message}"`); } // Mark this Fiber as needed its warning/error count updated during the next flush. <del> fibersWithChangedErrorOrWarningCounts.add(fiberID); </del> <ins> fibersWithChangedErrorOrWarningCounts.add(fiber); </ins> <del> // Update the error/warning messages and counts for the Fiber. const fiberMap = type === 'error' ? fiberToErrorsMap : fiberToWarningsMap; const messageMap = fiberMap.get(fiberID); </del> <ins> // Track the warning/error for later. const fiberMap = type === 'error' ? pendingFiberToErrorsMap : pendingFiberToWarningsMap; const messageMap = fiberMap.get(fiber); </ins> if (messageMap != null) { const count = messageMap.get(message) || 0; messageMap.set(message, count + 1); } else { <del> fiberMap.set(fiberID, new Map([[message, 1]])); </del> <ins> fiberMap.set(fiber, new Map([[message, 1]])); </ins> } <del> // If this Fiber is currently being inspected, mark it as needing an udpate as well. updateMostRecentlyInspectedElementIfNecessary(fiberID); </del> // Passive effects may trigger errors or warnings too; // In this case, we should wait until the rest of the passive effects have run, // but we shouldn't wait until the next commit because that might be a long time.

function reevaluateErrorsAndWarnings() { fibersWithChangedErrorOrWarningCounts.clear(); <del> fiberToErrorsMap.forEach((countMap, fiberID) => { fibersWithChangedErrorOrWarningCounts.add(fiberID); </del> <ins> fiberIDToErrorsMap.forEach((countMap, fiberID) => { const fiber = idToArbitraryFiberMap.get(fiberID); if (fiber != null) { fibersWithChangedErrorOrWarningCounts.add(fiber); } </ins> }); <del> fiberToWarningsMap.forEach((countMap, fiberID) => { fibersWithChangedErrorOrWarningCounts.add(fiberID); </del> <ins> fiberIDToWarningsMap.forEach((countMap, fiberID) => { const fiber = idToArbitraryFiberMap.get(fiberID); if (fiber != null) { fibersWithChangedErrorOrWarningCounts.add(fiber); } </ins> }); recordPendingErrorsAndWarnings(); } <del> function recordPendingErrorsAndWarnings() { clearPendingErrorsAndWarningsAfterDelay(); </del> <ins> function mergeMapsAndGetCountHelper( fiber: Fiber, fiberID: number, pendingFiberToMessageCountMap: Map<Fiber, Map<string, number>>, fiberIDToMessageCountMap: Map<number, Map<string, number>>, ): number { let newCount = 0; </ins> <del> fibersWithChangedErrorOrWarningCounts.forEach(fiberID => { const fiber = idToArbitraryFiberMap.get(fiberID); if (fiber != null) { // Don't send updates for Fibers that didn't mount due to e.g. Suspense or an error boundary. // We may also need to clean up after ourselves to avoid leaks. // See inline comments in onErrorOrWarning() for more info. if (isFiberMountedImpl(fiber) !== MOUNTED) { untrackFiberID(fiber); return; } </del> <ins> let messageCountMap = fiberIDToMessageCountMap.get(fiberID); </ins> <del> let errorCount = 0; let warningCount = 0; </del> <ins> const pendingMessageCountMap = pendingFiberToMessageCountMap.get(fiber); if (pendingMessageCountMap != null) { if (messageCountMap == null) { messageCountMap = pendingMessageCountMap; </ins> <del> if (!shouldFilterFiber(fiber)) { const errorCountsMap = fiberToErrorsMap.get(fiberID); const warningCountsMap = fiberToWarningsMap.get(fiberID); </del> <ins> fiberIDToMessageCountMap.set(fiberID, pendingMessageCountMap); } else { // This Flow refinement should not be necessary and yet... const refinedMessageCountMap = ((messageCountMap: any): Map< string, number, >); pendingMessageCountMap.forEach((pendingCount, message) => { const previousCount = refinedMessageCountMap.get(message) || 0; refinedMessageCountMap.set(message, previousCount + pendingCount); }); } } </ins> <del> if (errorCountsMap != null) { errorCountsMap.forEach(count => { errorCount += count; }); } if (warningCountsMap != null) { warningCountsMap.forEach(count => { warningCount += count; }); } } </del> <ins> if (!shouldFilterFiber(fiber)) { if (messageCountMap != null) { messageCountMap.forEach(count => { newCount += count; }); } } pendingFiberToMessageCountMap.delete(fiber); return newCount; } function recordPendingErrorsAndWarnings() { clearPendingErrorsAndWarningsAfterDelay(); fibersWithChangedErrorOrWarningCounts.forEach(fiber => { const fiberID = getFiberIDUnsafe(fiber); if (fiberID === null) { // Don't send updates for Fibers that didn't mount due to e.g. Suspense or an error boundary. } else { const errorCount = mergeMapsAndGetCountHelper( fiber, fiberID, pendingFiberToErrorsMap, fiberIDToErrorsMap, ); const warningCount = mergeMapsAndGetCountHelper( fiber, fiberID, pendingFiberToWarningsMap, fiberIDToWarningsMap, ); </ins> pushOperation(TREE_OPERATION_UPDATE_ERRORS_OR_WARNINGS); pushOperation(fiberID); pushOperation(errorCount); pushOperation(warningCount); } <ins> // Always clean up so that we don't leak. pendingFiberToErrorsMap.delete(fiber); pendingFiberToWarningsMap.delete(fiber); </ins> }); fibersWithChangedErrorOrWarningCounts.clear(); }

rootType = fiberRoot._debugRootType; } <del> const errors = fiberToErrorsMap.get(id) || new Map(); const warnings = fiberToWarningsMap.get(id) || new Map(); </del> <ins> const errors = fiberIDToErrorsMap.get(id) || new Map(); const warnings = fiberIDToWarningsMap.get(id) || new Map(); </ins> return { id,


Question:
Many of the issues created with the with the  template are missing repro information (e.g. a "localhost" or otherwise invalid URL, missing or no repro description). I usually have to review, label, comment, and close this by hand. It would be nice if we had an automated action that checked: Was the issue made with the  template? Does the URL section have an invalid URL (e.g. "localhost" or "company website") Does the repro steps section have invalid steps (e.g. "don't know") For issues that pass all of the above text, the bot should: Assign the "Resolution: Needs More Information" label Close the issue Leave a comment explaining that repro information was missing and that we'll re-open it if information is provided
Related action:
Going to play with this idea here:

<ins> name: DevTools Check for bug repro on: issues: types: [opened, edited] issue_comment: types: [created, edited] jobs: check-repro: runs-on: ubuntu-latest steps: - uses: actions/github-script@v3 with: github-token: ${{ secrets.GITHUB_TOKEN }} script: | const URL_REGEXP = /### Website or app[rn]+([^#]+)###/m; const REPRO_STEPS_REGEXP = /### Repro steps[rn]+([^#]+)###/m; const LABEL_NEEDS_MORE_INFORMATION = "Resolution: Needs More Information"; const LABEL_UNCONFIRMED = "Status: Unconfirmed"; function debug(...args) { core.info(args.map(JSON.stringify).join(' ')); } if (context.payload.comment) { debug('Ignoring comment update.'); return; } const user = context.payload.sender.login; const issue = context.payload.issue; const body = issue.body; const urlMatch = body.match(URL_REGEXP); const reproStepsMatch = body.match(REPRO_STEPS_REGEXP); const url = urlMatch !== null ? urlMatch[1].trim() : null; const reproSteps = reproStepsMatch !== null ? reproStepsMatch[1].trim() : null; if (!url || !reproSteps) { debug('This issue is not a DevTools bug report.'); return; } debug(`found URL "${url}"`); debug(`found repro steps "${reproSteps}"`); function formatComment(comment) { return comment .split("n") .map((line) => line.trim()) .join("n") .trim(); } async function getGitHubActionComments() { debug(`Loading existing comments...`); const comments = await github.issues.listComments({ issue_number: context.issue.number, owner: context.repo.owner, repo: context.repo.repo, }); return comments.data.filter(comment => { debug(`comment by user: "${comment.user.login}"`); return comment.user.login === 'github-actions[bot]'; }); } async function getIssueLabels() { const issues = await github.issues.listLabelsOnIssue({ issue_number: context.issue.number, owner: context.repo.owner, repo: context.repo.repo, }); return issues.data; } async function closeWithComment(comment) { if (issue.state !== 'open') { debug(`Issue is not open`); return; } const labels = await getIssueLabels(); const label = labels.find(label => label.name === LABEL_UNCONFIRMED); if (!label) { debug(`Issue was not opened via DevTools bug report template`); return; } const comments = await getGitHubActionComments(); if (comments.length > 0) { debug(`Already commented on issue; won't comment again`); return; } debug(`Missing required information`); await github.issues.addLabels({ issue_number: context.issue.number, owner: context.repo.owner, repo: context.repo.repo, labels: [LABEL_NEEDS_MORE_INFORMATION], }); await github.issues.createComment({ issue_number: context.issue.number, owner: context.repo.owner, repo: context.repo.repo, body: formatComment(comment), }); await github.issues.update({ issue_number: context.issue.number, owner: context.repo.owner, repo: context.repo.repo, state: 'closed', }); } async function openWithComment(comment) { if (issue.state !== 'closed') { debug(`Issue is already open`); return; } const labels = await getIssueLabels(); const label = labels.find(label => label.name === LABEL_NEEDS_MORE_INFORMATION); if (!label) { debug(`Issue was not tagged as needs information`); return; } const comments = await getGitHubActionComments(); if (comments.length === 0) { debug(`Issue was closed by someone else; won't reopen`); return; } debug(`Re-opening closed issue`); await github.issues.removeLabel({ issue_number: context.issue.number, owner: context.repo.owner, repo: context.repo.repo, name: LABEL_NEEDS_MORE_INFORMATION, }); await github.issues.createComment({ issue_number: context.issue.number, owner: context.repo.owner, repo: context.repo.repo, body: formatComment(comment), }); await github.issues.update({ issue_number: context.issue.number, owner: context.repo.owner, repo: context.repo.repo, state: 'open', }); } const PROBABLY_NOT_A_URL_REGEX = /(^Chrome$|^Firefox$| Website)/i; const COMMENT_HEADER = ` @${user}: We're sorry you've seen this error. ❤ `.trim(); const COMMENT_FOOTER = ` Please help us by providing a link to a CodeSandbox (https://codesandbox.io/s/new), a repository on GitHub, or a minimal code example that reproduces the problem. (Screenshots or videos can also be helpful if they help provide context on how to repro the bug.) Here are some tips for providing a minimal example: https://stackoverflow.com/help/mcve Issues without repros are automatically closed but we will re-open if you update with repro info. `.trim(); if (url.includes("/localhost")) { closeWithComment(` ${COMMENT_HEADER} Unfortunately the URL you provided ("localhost") is not publicly accessible. (This means that we will not be able to reproduce the problem you're reporting.) ${COMMENT_FOOTER} `); } else if (url.length < 10 || url.match(PROBABLY_NOT_A_URL_REGEX)) { closeWithComment(` ${COMMENT_HEADER} It looks like you forgot to specify a valid URL. (This means that we will not be able to reproduce the problem you're reporting.) ${COMMENT_FOOTER} `); } else if (reproSteps.length < 25) { closeWithComment(` ${COMMENT_HEADER} Unfortunately, it doesn't look like this issue has enough info for one of us to reproduce and fix it though. ${COMMENT_FOOTER} `); } else { openWithComment(` Thank you for providing repro steps! Re-opening issue now for triage. `); } </ins>


Question:
Provided is a code sandbox with a very simplified version of the code which triggered this bug. the code sandbox app in a new window developer tools the "Components" tab on the "App" component Observe that devtools crashed, and the console prints out an error similar to this: This happens in both Firefox and Chrome. Every time react-devtools-extensions 13.5- Could not inspect element with id 2 No response
I see a slightly different error than the one reported: I can repro this though so that's good. I can fix this.
Fix will go out with the next release.
Not sure what your release cycle is, but I'm using the extension built from source in the meantime. Works fine now, thanks!
I have a similar issue. I created a PR that should fix the crash: To reproduce: clone into install dependencies run application: open the -Tab in click on the component you should see following error: !
I would appreciate if you could make a reduced repro that didn't import other frameworks (like this i18n framework). Seems like the core of this problem is related, but I'm having to dig through unfamiliar (TypeScript) code trying to narrow down why it's still throwing in .
thanks for your help! I simplified the example a bit and marked the key-part. Just replace the file with following content: jsx import React from 'react' export const getFallbackProxy = (prefixKey?: string): any =new Proxy((prefixKey ? () =prefixKey : {}) as any, { get: (_target, key: string) =getFallbackProxy(prefixKey ? : key), }) export const initI18nReact = () ={ const context = React.createContext({} as any) const Component: React.FunctionComponent<{ initialLocale: string }= (props) ={ const [isLoadingLocale, setIsLoadingLocale] = React.useState<boolean(false) const [currentLocale, setCurrentLocale] = React.useState<string | null(null) const [LL, setLL] = React.useState(getFallbackProxy()) const setLocale = async (newLocale: string): Promise<void={ setIsLoadingLocale(true) setLL( //
// KEY-PART BEGIN --------------------------------------------------------------------- //
new Proxy( {}, { get: (target: any, key: string) ={ (, key) return () =key }, }, ) as any, //
// KEY-PART END --------------------------------------------------------------------- //
) setCurrentLocale(newLocale) setIsLoadingLocale(false) } !currentLocale && !isLoadingLocale && setLocale((props as any).initialLocale 'en') if (!isLoadingLocale && !LL) { return null } const ctx = { setLocale, isLoadingLocale, locale: currentLocale, LL } return <context.Provider value={ctx}{props.children}</context.Provider} return { component: Component, context } } //
const { component: TypesafeI18n, context: I18nContext } = initI18nReact() export { I18nContext } export default TypesafeI18n and then run When you look at the console output you can see all access-attempts to the proxy being logged: ! The uppercased names come from the application-code itself. Then it gets interesting.. React Dev Tools tries to access that proxy with a lot of different keys, the Proxy can not handle (and should not handle). Not so sure where this gets called and I currently don't have a lot time to dig deeper.. I assume this PR is 'fixing' the wrong thing since the problem lays somewhere else.
I'm seeing a different error from the repro you shared above: The error I was seeing on the PR was:
But you see all the accesses to the Proxy from React Dev Tools? Forget the error for now. If we can tell React Dev Tools to not access the Proxy, the error should be gone.
It's not as simple as that. When an element is inspected, DevTools must serialize its props/state/hooks (using ) to send values from the "backend" (running in the page with your app) to the "frontend" (DevTools extension UI). (These are in separate memory spaces, so we can't just share the value directly.) As a side note, it also needs to avoid deeply cloning objects because that can add a lot of overhead and slow things down, so instead it shallowly clones them before serializing. The main utility that does this is here: The code path that's triggering all of the accesses you're pointing out is here: Which calls this function to loop over props: Then eventually this method throws when trying to stringify a property: More specifically, this line: Calling with the proxy value throws. Replacing that method of mapping keys with a that pushes to an array also throws. You can reproduce this error with the following stripped down code: Q: Why can't you just treat this Proxy object differently? A: Because (to my knowledge) there is no way to determine if a value is a . Q: Is there a workaround for this? A: You could make your detectable using the operator, but it would require custom work on your side to support. You could also defined a custom accessor to limit the values that were iterated over. Q: Is there something (hacky) that DevTools could do to detect this case. A: Maybe? Maybe we could check something like to detect an edge case like this, but I'm not sure if this would have other negative consequences. I'm also not sure what we would do with it once we had detected it. Just show a special shallow "[[Proxy]]" string or something? It wouldn't be inspectable.
thanks for your detailed analysis. In my opinion the best solution would be to define the method on the proxy-handler. I tested it with the current React Dev Tools but it seems you don't jet check the available properties with am I right? So work on both ends would be required.
This sounds like a reasonable approach. That's right. I don't think it's generally desirable that we limit the values displayed to being only properties found directly on the object. That being said, maybe we could do something like this as a fallback. However, even after doing something like this, I'm seeing a different runtime error. I would welcome proposals/contributions from you to improve the way DevTools works with edge case objects like the type of Proxy this library uses.
not so sure if detecting a proxy by the content of the error-message is a good solution. the wording could change different browsers may have different wording I recently saw a localized DevTool environment, so maybe also the error-messages are not english Is there another way to check if we access an object? Maybe use something like:
I don't think that approach makes sense. If it's already an array, we wouldn't need to convert it. The purpose of calling is to simplify handling different types of iterables. That being said, I think even if we solve the iteration issue (which the error message check does, even if not in a very robust way) I think we'll still have other issues.
Ah, sorry, I didn't check the context of that array example. This code is here to display a graphical representation of an object somewhere inside the React Dev Tools? I think a better solution would be to change this to and add a new case inside the function that uses (data)
I don't think the above code works, because it would hit false positives for HTML collectins or regular expressions. The only way I know of to check this would be to use the non-standard property (which seems like not a great idea).
in other words: we are not able to find a solution to the problem? So also HTML collections and regular expressions throw an error in the same line as a Proxy? But looking at the function you have already a way to detect these two types. So I don't see why the code mentioned above should not work. It could indeed create false positives, but at least it will not throw an error.
That is correct. They would if you tried to invoke . Look at the surrounding code: We only enter the code path for "iterator" (and "opaque_iterator"). Your proposal, seemingly, was to enter it always and interpret a as a Proxy detection. This would break the other types I mentioned. Alternately, if we left this check in place, then the / would never run for Proxies:
I just created a PR that shows the implementation I would imagine. It has no side-effect on the detection of regular expressions and collections. It just handles cases, where accessing and executing e.g. the property of a proxy throws an error.
I tried an approach very similar and it didn't work for me (in Node) until I removed the check above. That's interesting. can you add a failing test to
yes, just give me a few days to find time for that
Sounds good!

`); }); <ins> // See github.com/facebook/react/issues/21654 it('should support Proxies that dont return an iterator', async () => { const Example = () => null; const proxy = new Proxy( {}, { get: (target, prop, receiver) => { target[prop] = value => {}; return target[prop]; }, }, ); const container = document.createElement('div'); await utils.actAsync(() => ReactDOM.render(<Example proxy={proxy} />, container), ); const inspectedElement = await inspectElementAtIndex(0); expect(inspectedElement.props).toMatchInlineSnapshot(` Object { "proxy": Object { "$$typeof": Dehydrated { "preview_short": ƒ () {}, "preview_long": ƒ () {}, }, "Symbol(Symbol.iterator)": Dehydrated { "preview_short": ƒ () {}, "preview_long": ƒ () {}, }, "constructor": Dehydrated { "preview_short": ƒ () {}, "preview_long": ƒ () {}, }, }, } `); }); </ins> describe('$r', () => { it('should support function components', async () => { const Example = () => {

// but this seems kind of awkward and expensive. return 'array_buffer'; } else if (typeof data[Symbol.iterator] === 'function') { <del> return data[Symbol.iterator]() === data ? 'opaque_iterator' : 'iterator'; </del> <ins> const iterator = data[Symbol.iterator](); if (!iterator) { // Proxies might break assumptoins about iterators. // See github.com/facebook/react/issues/21654 } else { return iterator === data ? 'opaque_iterator' : 'iterator'; } </ins> } else if (data.constructor && data.constructor.name === 'RegExp') { return 'regexp'; } else {


Question:
Website is actually irrelevant, but required. the devtools the settings button. the layout being broken (causing horizontal scrollbar). Screenshot ! Every time No response No response No response No response No response No response
Can you provide some more information? Browser (and version), operating system (and version), DevTools extension version, etc. I can't reproduce this.
Firefox 89, Windows 10, latest extension. It's really not that far-fetched.
I'm not sure why there's hostility in your responses (both to this issue and ). This is a free software product and I'm trying to help you. Providing basic info like browser and operating system version along with a bug report is generally useful, regardless of how far fetched you think the configuration is :smile:
Not sure if this is confirmed by anyone else, but I can reproduce this on Firefox. I'll paste my device information so you can try that out in order to repro. How it looks: ! Machine: Windows 10 Home Browser: Firefox version 89.0.1 (64-bit) Let me know if you need more details, I'll be more than happy to take this up. Update: It also happens on chrome dev tools when you resize your dev tools to some specific width.
If I enable scroll bars on OS X, I can also reproduce this in Firefox. Should be able to fix it then. (Did not have access to a Windows machine to test with.) Edit 1: It looks like this is caused by the tab bar containing too many tabs now (General, Debugging, Components, Profiler, and "x" button). Should be an easy fix. Edit 2: I think the reason for the difference between Firefox and Chrome is that the (supposedly hidden) buttons used for the Tab bar accessibility isn't 0 width for Firefox.
Sorry mate, but I don't understand the question then. You asked for browser & OS, and I gave that exact answer. That's really, honestly, genuinely, everything needed to a repro. I've seen this on every pc running Windows 10 + Firefox so far, which is why it's not that far-fetched. I don't see how that's hostile. And actually, we're trying help each other, aren't we Also how am I responding hostile in ? I'm suggesting a fix. I'm Dutch, so I'm just being direct, not hostile at all. It's my culture, please respect that

box-shadow: 0 2px 4px var(--color-shadow); border-radius: 0.25rem; overflow: auto; <del> width: 400px; </del> <ins> width: 410px; </ins> max-width: 100%; }

user-select: none; color: var(--color-text); <ins> /* Hide radio buttons for Firefox too */ position:  relative; </ins> /* Electron drag area */ -webkit-app-region: no-drag; }

width: 0; margin: 0; opacity: 0; <ins> /* Hide radio buttons for Firefox too */ position:  absolute; </ins> } .IconSizeNavigation,


Question:
DevTools tells Babel to parse the source code using "jsx" and "typescript" plug-ins: This will work for some simple usages of Flow, but syntax may diverge and cause the parsing to fail. Let's scan the source code for a pragma and pass "flow" instead of "typescript" if one is found. We should also add tests for both Flow and TypeScript to the test component pool:
I think something as basic as this should work:

hookSourceData.originalSourceAST = sourceMetadata.originalSourceAST; hookSourceData.originalSourceCode = sourceMetadata.originalSourceCode; } else { <ins> // TypeScript is the most commonly used typed JS variant so let's default to it // unless we detect explicit Flow usage via the "@flow" pragma. const plugin = originalSourceCode.indexOf('@flow') > 0 ? 'flow' : 'typescript'; </ins> // TODO (named hooks) Parsing should ideally be done off of the main thread. const originalSourceAST = parse(originalSourceCode, { sourceType: 'unambiguous', <del> plugins: ['jsx', 'typescript'], </del> <ins> plugins: ['jsx', plugin], </ins> }); hookSourceData.originalSourceAST = originalSourceAST; if (__DEBUG__) {


Question: This can cause long file names (URLs) to be truncated which in turn will break named hooks code (since it needs to load those file names).

import type {SourceConsumer} from './astUtils'; const SOURCE_MAP_REGEX = / ?sourceMappingURL=([^s'"]+)/gm; <del> const ABSOLUTE_URL_REGEX = /^https?:///i; </del> const MAX_SOURCE_LENGTH = 100_000_000; type AST = mixed;

} let url = sourceMappingURLs[i].split('=')[1]; <del> if (ABSOLUTE_URL_REGEX.test(url)) { const baseURL = url.slice(0, url.lastIndexOf('/')); url = `${baseURL}/${url}`; if (!isValidUrl(url)) { throw new Error(`Invalid source map URL "${url}"`); } } else if (!url.startsWith('/')) { </del> <ins> if (!url.startsWith('http') && !url.startsWith('/')) { </ins> // Resolve paths relative to the location of the file name const lastSlashIdx = runtimeSourceURL.lastIndexOf('/'); if (lastSlashIdx !== -1) {

return map; } <del> function isValidUrl(possibleURL: string): boolean { try { // eslint-disable-next-line no-new new URL(possibleURL); } catch (_) { return false; } return true; } </del> function loadSourceFiles( locationKeyToHookSourceData: Map<string, HookSourceData>, ): Promise<*> {

// Never dehydrate the "hooks" object at the top levels. return true; } <ins> if ( path[path.length - 2] === 'hookSource' && path[path.length - 1] === 'fileName' ) { // It's important to preserve the full file name (URL) for hook sources // in case the user has enabled the named hooks feature. // Otherwise the frontend may end up with a partial URL which it can't load. return true; } </ins> if ( path[path.length - 1] === 'subHooks' || path[path.length - 2] === 'subHooks'

}; case 'string': <del> return data.length <= 500 ? data : data.slice(0, 500) + '...'; </del> <ins> isPathAllowedCheck = isPathAllowed(path); if (isPathAllowedCheck) { return data; } else { return data.length <= 500 ? data : data.slice(0, 500) + '...'; } </ins> case 'bigint': cleaned.push(path);


Question: The named hooks cache returns The first (mixed array of string and null) indicates an overall success, even if some names couldn't be inferred. The second indicates an error (e.g. couldn't locate or load source map). In the event of the 2nd response type, the UI currently does nothing (falls back to default) but we should show an error badge (maybe a disabled but red icon with a tooltip saying there was an error) since it's a confusing user experience to just do nothing.

inspectElement, } from 'react-devtools-shared/src/inspectedElementCache'; import {loadHookNames} from 'react-devtools-shared/src/hookNamesCache'; <del> import {ElementTypeFunction} from 'react-devtools-shared/src/types'; </del> import LoadHookNamesFunctionContext from 'react-devtools-shared/src/devtools/views/Components/LoadHookNamesFunctionContext'; import {SettingsContext} from '../Settings/SettingsContext';

if (parseHookNames) { if ( inspectedElement !== null && <del> inspectedElement.type === ElementTypeFunction && </del> inspectedElement.hooks !== null && loadHookNamesFunction !== null ) {

.HookName { color: var(--color-component-name); <ins> } .ToggleError { color: var(--color-error-text); </ins> }  No newline at end of file

toggleParseHookNames(); }; <ins> const hookParsingFailed = parseHookNames && hookNames === null; let toggleTitle; if (hookParsingFailed) { toggleTitle = 'Hook parsing failed'; } else if (parseHookNames) { toggleTitle = 'Parsing hook names ...'; } else { toggleTitle = 'Parse hook names (may be slow)'; } </ins> const handleCopy = () => copy(serializeHooksForCopy(hooks)); if (hooks === null) {

hooks
  {enableHookNameParsing && !parseHookNames && (   {enableHookNameParsing && (!parseHookNames || hookParsingFailed) && (  <Toggle  className={hookParsingFailed ? styles.ToggleError : null}  isChecked={parseHookNamesOptimistic}  isDisabled={parseHookNamesOptimistic}   isDisabled={parseHookNamesOptimistic || hookParsingFailed}  onChange={handleChange}  title={ parseHookNames ? 'Parse hook names' : 'Parse hook names (may be slow)' }>   title={toggleTitle}>  <ButtonIcon type="parse-hook-names" /> </Toggle> )}


Question:
devtools "Components" tab At first the component tree won't appear. Once I'm at the "Components" tab, I then have to also refresh the page to make the tree render. And when it does render, it still doesn't work properly. As a note, this issue started happening after I had to forcibly restart my computer. Since then I have tried reinstalling the extension, restarting Chrome, restarting my pc, all of which haven't worked. I'd like to avoid reinstalling Chrome completely but that's the only thing I haven't yet tried. Using Windows 10, btw. Here is what the broken component tree looks like. It's very narrow and the components cannot be selected: ! Every time No response No response No response No response No response No response
Same issue, Chrome v 92.0.4515.107
Same here: ! The Profiler tab seems unaffected Workarounds that don't help: Reloading the page Docking the devtools on the side/bottom Undocking the devtools (a.k.a. open in a window) Resizing the window Fiddling with the setting Resizing the right pane of the component tab
Looks like a CSS issue. I managed to work around it by fiddling with the styles as shown in this video: https://user- Besides the css tweaks to make the tree not so squished, the mouse selection issue has to be worked around separately The nodes are initially selectable with the mouse, but mouse selection breaks permanently if you attempt to use the element picker (I'm guessing it adds and doesn't remove it?) Using other methods of selecting nodes (i.e. searching, keyboard, using the / buttons, etc) still work For anyone curious on how to do what I did in the video: the devtools in undocked mode this will open an "inspector inspector" the properties as shown in the video
Doesn't seem to occur on mac os for me on extension (both from chrome extension store and running from main branch). Could this be os specific? Version 14.0 (7/16/2021) <img width="1674" alt="Screenshot 2021-07-30 at 00 05 56" src="https://user-"
reproduces for me on: MacOS X 10.14 Chrome Version 92.0.4515.107 (Official Build) (x86_64) (latest) DevTools 4.14.0 (7/16/2021)
Mine is: Windows 10 21H1 (OS Build .1110) Chrome Version 92.0.4515.107 (Official Build) (64-bit) DevTools version 4.14.0- If any developer is unable to reproduce, let me know and I can get you whatever you need (a snapshot of the dom, the css ruleset, a memory dump, of specific nodes, heck even a css fiddle if that's what you need, anything that might help you) Also I know you guys know this but just in case: what I did in the video is by no means a suggestion of what should be done in order to fix the problem. Randomly changing CSS around without understanding what it does is a good way to introduce more bugs
reproduces for me on: Windows 10 Pro (10.0. Build ) Edge Version 92.0.902.62 (Official Build) (64-bit) (latest) DevTools 4.14.0 (7/16/2021)
I also have this problem: MacOS 11.4 Chrome version: Version 92.0.4515.131 (Official Build) (x86_64) DevTools version: 4.14.0 (7/16/2021) Sometimes component tree doesn't show at all, have to reload a page. Even after reloading tree is too narrow and clicks are not coming through. Tried every sane approach to fix (reinstall, reload etc) — nothing helps.
Occurs for me as well: Ubuntu 20.04.2 LTS Chrome: 92.0.4515.107 - also occurs on: 92.0.4515.131 DevTools: 4.14.0 While Chrome is affected for me - FireFox continues to work.
Another report in
I suspect the bug may be caused by this component (which we use in DevTools to auto-expand the Components tree to fill the width and height of the viewport):
Me too. OSX Chrome (the latest) ReactDevTools: Interestingly, the issue is not present in (Brave ).
Tanks As another data point: OS X 11.4 (20F71) Chrome 92.0.4515.131 DevTools (built from HEAD of ) FWIW I've never seen or been able to reproduce this bug myself (and I use DevTools daily). Maybe others can share their configurations and we can spot a pattern.
@ bvaughn So you can't reproduce? What would be helpful for you to track this down?
I have the same issues and also using chrome with latest version and dev tools version on windows 10. Weird thing, is my co-worker with the same versions, it works fine on his end on the same app/site. So no idea what is causing it to not work on my computer.
Could be helpful if you and your coworker could try to further narrow down what the difference is between the two of your setups.
I checked with him quickly and we have pretty much the same extensions. I also did a test in Edge and in Edge it works fine, it only seems to affect my chrome. I also tried to disable all extensions and even did a complete reset of the chrome settings to default values and cleared all cache. The problem still persists. I even thought of disabling hardware acceleration and checked if my settings differed from edge, but no go.
I have a suspicion at whats going on here. I know react-virtualized ~shims ~ has resize detection using scroll event handlers, when it does this, it schedules a to be notified after the layout updates. In this case, if I debug this script, I can see that scheduling any raf in of the devtool will never fire. I suspect a finch trial is being used by the Chromium team to attempt to throttle rAFs in hidden s. This experiment looks the most suspicious, these will show as "Default" for everyone unfortunately. !
Awesome work, this pretty much confirms it. Changing that flag from to solves the issue on my end. Changing it to makes it happen again
Couldn't find the throttle setting mentioned by and where to change it. But I uninstalled chrome completely and reinstalled it (fresh copy, wiping out all settings) and it fixed it for me.
Could be worth opening a Chromium ticket, but from similar experience this is likely by design. Maybe they could exclude devtools extensions here? I think the fact that this is deep in the ~ polyfill~ resize detection might make it painful to fix in the short term. Maybe it's best to create a branch off of thats used for the plugin that from the scheduler array Alternatively it feels like that ~polyfill~ detection deserves a naive check around and preferring over when hidden.
Fantastic find, Seems like could detect this case (no rAF firing by a certain time) and maybe fallback to using a timer or other debounce technique.
I saw you just picked this up if you have issues in development I have seen Chromium make timers minute aligned when doing background throttling. It's possible it may do the same in this case. If that's the case I know setImmediate polyfills have a trick with a self that could be used.
Thanks for the pointer, Happen to have a code pointer?
Sure! Here's the strategy I was thinking of and here is a reference to the timer alignment I've seen mentioned (not 100% sure it will apply here)
Super helpful. Thanks!
I'm overlooking some important detail here. Enabling/disabling the "Throttle non-visible cross-origin iframes" flag does indeed trigger/fix the bug, but even when this is disabled– animation frames still get called based on my testing, unlike what reported above: (So my idea to detect this case and fallback to a timeout doesn't work.) That being said, just replacing with (and not trying to detect support) fixes the broken behavior.
ah interesting. Just to validate are you registering those callbacks from the context of or . I believe they will only fail to fire from (which is the hidden iframe)
I logging to the feature detection code I wrote (which runs in the same context as the script).
Fixed it by adding a fallback timeout when rAF is used Doesn't feel great but...
Thanks a ton for the info and
This fix has landed. We'll probably release it next week because we're also waiting on another bugfix to unblock the Firefox release.
Related CR bug:

"memoize-one": "^5.1.1", "nullthrows": "^1.1.1", "pretty-ms": "^7.0.0", <del> "react-virtualized-auto-sizer": "^1.0.2", </del> <ins> "react-virtualized-auto-sizer": "^1.0.6", </ins> "regenerator-runtime": "^0.13.7" }, "devDependencies": {

"local-storage-fallback": "^4.1.1", "lodash.throttle": "^4.1.1", "memoize-one": "^3.1.1", <del> "react-virtualized-auto-sizer": "^1.0.2", </del> <ins> "react-virtualized-auto-sizer": "^1.0.6", </ins> "semver": "^6.3.0" } }

resolved "https://registry.yarnpkg.com/react-timer-mixin/-/react-timer-mixin-0.13.4.tgz#75a00c3c94c13abe29b43d63b4c65a88fc8264d3" integrity sha512-4+ow23tp/Tv7hBM5Az5/Be/eKKF7DIvJ09voz5LyHGQaqqz9WV8YMs31eFvcYQs7d451LSg7kDJV70XYN/Ug/Q== <del> react-virtualized-auto-sizer@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/react-virtualized-auto-sizer/-/react-virtualized-auto-sizer-1.0.2.tgz#a61dd4f756458bbf63bd895a92379f9b70f803bd" integrity sha512-MYXhTY1BZpdJFjUovvYHVBmkq79szK/k7V3MO+36gJkWGkrXKtyr4vCPtpphaTLRAdDNoYEYFZWE8LjN+PIHNg== </del> <ins> react-virtualized-auto-sizer@^1.0.6: version "1.0.6" resolved "https://registry.yarnpkg.com/react-virtualized-auto-sizer/-/react-virtualized-auto-sizer-1.0.6.tgz#66c5b1c9278064c5ef1699ed40a29c11518f97ca" integrity sha512-7tQ0BmZqfVF6YYEWcIGuoR3OdYe8I/ZFbNclFlGOC3pMqunkYF/oL30NCjSGl9sMEb17AnzixDz98Kqc3N76HQ== </ins> react@^16.13.1: version "16.13.1"


Question:
I encountered the same issue as but using as a stand-alone app instead of from the the browser. The bottom line is that the profiler becomes unresponsive after any interaction with a heavily loaded react page. React version: React: 17.0.2 ReactDOM: 17.0.2 React Devtools: 4.18.0 a react-devtools stand-alone () to a session profiling something on your app that would cause a huge number of updates profiler stops functioning I actually went through and found out the origin of the issue, however I am not sure what would be the best approach to fix it. It seems the the origin is a (very) big incoming message: <img width="516" alt="image" src="https://user-"That eventually causes a maximum call stack exceeded error: <img width="522" alt="image" src="https://user-"Coming from : And interestingly enough, doing spread operator with an array with elements actually causes a error I tried replacing the code above with the following replacement and it seems to work:
Can you share a repro case with me please? I'd love to verify the fix (and if possible maybe even add an automated regression test– although this might not be possible, given the underlying problem seems to be with the generated code not the source code).
That is interesting! I don't think this is true for the native spread operator. For example, this runs okay for me in Chrome: I'm pretty sure this has to do with the code that's generated in the build (for backwards compat): This throws as you describe:
Actually I think this depends on the function. Indeed your array example works as expected, but try this: For me it fails natively on chrome EDIT: I just realised you are doing a spread operator on an array. This is trivially translated into a call and the stack is not used. However if you try to use the spread operation in a function call, all the function arguments must be first placed on stack before the function is called (per standard JS function call procedure). This means that if the array is big enough, you will exhaust your stack. Unfortunately my project structure is pretty complex to identify just one possible code path that is causing that issue. My best guess is that it's happening when I am replacing (un-mounting and re-mounting) a couple of thousand of child elements at once. I can try to isolate a reproducible example it but it will take some time... If it suits you though, I can easily give you a JSON dump of the contents of the said "operations" event that caused the exception.
Nice follow up information! Thanks! Fair enough. I think we can proceed without a repro in this case.

} export function utfDecodeString(array: Array<number>): string { <del> return String.fromCodePoint(...array); </del> <ins> // Avoid spreading the array (e.g. String.fromCodePoint(...array)) // Functions arguments are first placed on the stack before the function is called // which throws a RangeError for large arrays. // See github.com/facebook/react/issues/22293 let string = ''; for (let i = 0; i < array.length; i++) { const char = array[i]; string += String.fromCodePoint(char); } return string; </ins> } export function utfEncodeString(string: string): Array<number> {


Question:
Any client that connects to the standalone DevTools While using the standalone DevTools app: a client to the DevTools that client and you should be redirected to the introduction page The event listeners are not re-attached to the splash page elements after the client disconnects. The <scripttags that can be copied on click and the "Profiler tab" link stop working. Every time No response No response No response No response No response No response
I was thinking about two ways to fix this issue: set a MutationObserver to re-attach the listeners when the contents of the root node are changed, or add a callback to the DevToolsUI in the core of the standalone version and re-attach the listeners on that callback.
Nice find! If you'd be interested in submitting a proposal (PR) I'd be happy to review and discuss.
Sure thing, will do!

installHook(window); export type StatusListener = (message: string) => void; <ins> export type OnDisconnectedCallback = () => void; </ins> let node: HTMLElement = ((null: any): HTMLElement); let nodeWaitingToConnectHTML: string = ''; let projectRoots: Array<string> = []; let statusListener: StatusListener = (message: string) => {}; <ins> let disconnectedCallback: OnDisconnectedCallback = () => {}; </ins> // TODO (Webpack 5) Hopefully we can remove this prop after the Webpack 5 migration. function hookNamesModuleLoaderFunction() {

return DevtoolsUI; } <ins> function setDisconnectedCallback(value: OnDisconnectedCallback) { disconnectedCallback = value; return DevtoolsUI; } </ins> let bridge: FrontendBridge | null = null; let store: Store | null = null; let root = null;

safeUnmount(); node.innerHTML = nodeWaitingToConnectHTML; <ins> disconnectedCallback(); </ins> } function onError({code, message}) {

setContentDOMNode, setProjectRoots, setStatusListener, <ins> setDisconnectedCallback, </ins> startServer, openProfiler, };

const server = defaultPort ? `${protocol}://${host}` : `${protocol}://${host}:${port}`; const serverIp = defaultPort ? `${protocol}://${localIp}` : `${protocol}://${localIp}:${port}`; const $ = document.querySelector.bind(document); <del> const $promptDiv = $("#box-content-prompt"); const $confirmationDiv = $("#box-content-confirmation"); </del> let timeoutID; function selectAllAndCopy(event) { const element = event.target; if (window.getSelection) {

selection.removeAllRanges(); selection.addRange(range); clipboard.writeText(event.target.textContent); <ins> const $promptDiv = $("#box-content-prompt"); const $confirmationDiv = $("#box-content-confirmation"); </ins> $promptDiv.classList.add('hidden'); $confirmationDiv.classList.remove('hidden');

.openProfiler(); } <del> const link = $('#rn-help-link'); link.addEventListener('click', event => { event.preventDefault(); require('electron').shell.openExternal(link.href); }); const $localhost = $("#localhost"); $localhost.innerText = `<script src="${server}"></` + 'script>'; $localhost.addEventListener('click', selectAllAndCopy); $localhost.addEventListener('focus', selectAllAndCopy); const $byIp = $("#byip"); $byIp.innerText = `<script src="${serverIp}"></` + 'script>'; $byIp.addEventListener('click', selectAllAndCopy); $byIp.addEventListener('focus', selectAllAndCopy); </del> <ins> function attachListeners() { const link = $('#rn-help-link'); link.addEventListener('click', event => { event.preventDefault(); require('electron').shell.openExternal(link.href); }); const $localhost = $("#localhost"); $localhost.innerText = `<script src="${server}"></` + 'script>'; $localhost.addEventListener('click', selectAllAndCopy); $localhost.addEventListener('focus', selectAllAndCopy); const $byIp = $("#byip"); $byIp.innerText = `<script src="${serverIp}"></` + 'script>'; $byIp.addEventListener('click', selectAllAndCopy); $byIp.addEventListener('focus', selectAllAndCopy); const $profiler = $("#profiler"); $profiler.addEventListener('click', openProfiler); }; </ins> <del> const $profiler = $("#profiler"); $profiler.addEventListener('click', openProfiler); </del> <ins> // Initially attach the listeners attachListeners(); </ins> let devtools; try {

window.devtools = devtools; window.server = devtools .setContentDOMNode(document.getElementById("container")) <ins> .setDisconnectedCallback(attachListeners) </ins> .setStatusListener(function(status) { const element = document.getElementById("loading-status"); if (element) {


Question: React DevTools v4.20.0 in Firefox in Firefox Firefox DevTools error in console ! Every time

declare var chrome: any; import {__DEBUG__} from 'react-devtools-shared/src/constants'; <ins> import {getBrowserName} from './utils'; </ins> import { EXTENSION_INSTALL_CHECK, EXTENSION_INSTALLATION_TYPE,

LOCAL_EXTENSION_ID, } from './constants'; <ins> const IS_CHROME = getBrowserName() === 'Chrome'; </ins> const UNRECOGNIZED_EXTENSION_ERROR = 'React Developer Tools: You are running an unrecognized installation of the React Developer Tools extension, which might conflict with other versions of the extension installed in your browser. ' + 'Please make sure you only have a single version of the extension installed or enabled. ' +

break; } case 'unknown': { <del> // If we don't know how this extension was built, we can't reliably detect if there // are other installations of DevTools present. // In this case, assume there are no duplicate exensions and show a warning about // potential conflicts. console.error(UNRECOGNIZED_EXTENSION_ERROR); chrome.devtools.inspectedWindow.eval( `console.error("${UNRECOGNIZED_EXTENSION_ERROR}")`, ); </del> <ins> // TODO: Support duplicate extension detection in other browsers if (IS_CHROME) { // If we don't know how this extension was built, we can't reliably detect if there // are other installations of DevTools present. // In this case, assume there are no duplicate exensions and show a warning about // potential conflicts. console.error(UNRECOGNIZED_EXTENSION_ERROR); chrome.devtools.inspectedWindow.eval( `console.error("${UNRECOGNIZED_EXTENSION_ERROR}")`, ); } </ins> callback(false); break; }


Question:
This started after last update 4.20.0 ! ! Every time No response No response No response No response No response No response
We're sorry you've seen this error. Unfortunately the URL you provided ("localhost") is not publicly accessible. (This means that we will not be able to reproduce the problem you're reporting.) Please help us by providing a link to a CodeSandbox (), a repository on GitHub, or a minimal code example that reproduces the problem. (Screenshots or videos can also be helpful if they help provide context on how to repro the bug.) Here are some tips for providing a minimal example: Issues without repros are automatically closed but we will re-open if you update with repro info.
Thank you for providing repro steps! Re-opening issue now for triage.
Sorry for the "Website or app " But it just didnt work with "Website or app localhost"
I've just stumbled across the same issue, but i think i may have managed to find a workaround to the bug for now, which is to navigate to another external third-party React website (eg, , , ), and then navigate back to your localhost site, while keeping Chrome DevTools React Developer Tools open throughout the process. Give that a go? Note: Not all external public third party React sites work with the workaround approach. So for example, navigating to other public React sites such as Facebook, Instagram, and Paypal does not appear to work as a temporary workaround. _ Chrome @ React Developer Tools @
I've tried with netflix but it doesn't seem to work, sadly =( thanks for your advise anyways! may be it will help someone else
I've updated my original comment, with the addition of React site, which is proven to also reliably work as a workaround for me, so try that too. But also found it does not work with the PayPal React site as a workaround. Besides that, i agree, this is a regression bug
Sadly didn't work as well
Does React Dev Tools load up elements when you navigate to ReactJS, Netflix or CNN? If not then, here is a refined step-by-step set of instructions for a workaround: Open a new tab Ensure Chrome Dev Tools is not open at all Navigate to (loads faster) Open Chrome Dev Tools React Dev Tools The React elements should load up and display for site (probably most important here) Click on any React element within React Dev Tools (preferably a React element that actually holds both props + state values, where that data would then be displayed to the right panel) Now navigate to your localhost site
The reason the GitHub bot asked for a URL that we could access (not "localhost") is because there might be something specifically going on with your local website version. Localhost apps in general work fine with DevTools. In fact, we use a running on localhost to build DevTools features. So the first question I would ask is: Does React DevTools work on other sites? For example, if you visit , does DevTools work? If so, this may suggest there's something specific with your website. If not, it may suggest that you have another extension installed that's interfering. If this is the case, it would be helpful for you to tell us which extensions you have installed (you can view this in about:extensions).
This bug also affected my colleague as of today, where the workaround i posted resolved the issue for now, for both me and my colleague, and his version of React Dev Tools is also at . Besides, as requested, here's my list of enabled Chrome extensions: Awesome Screenshot and Screen Recorder | The Homepage Developers Deserve Ghostery – Privacy Ad Blocker Google Docs Offline Honey Octotree - GitHub code tree Picture-in-Picture Extension (by Google) React Developer Tools Redux DevTools Treeverse Chrome @ React Developer Tools @
Yes React DevTools work on other sites. I've tried to disable all extensions, nothing changed. DevTools worked perfectly fine until last friday (15.10) and since then nothing changed in my project.
cc in case this could be related to ?
yeah sounds like this might be related, I'll investigate
to confirm, the issue is that you open the Components tab but the Components Tree never loads? and this only happens on localhost when developing your app locally? is this happening to you on Chrome?
Yes and yes
- The scenario you've described is correct. Essentially the Component Tree never loads, until i apply my workaround.
do you by any chance have another repro of this in any other website that isn't your localhost development app? or a way to reproduce with your local app?
Sadly, i can't provide you a webside for NDA reasons
We generally ask people to try to reduce bugs to a minimal repro case. Often this is enough for them to remove any sensitive stuff from the app. (Often folks will even realize the specific cause of a bug while doing this.) Can you try stripping things out of your app until it works to see if you can create a repro like this for us?
like Brian mentioned, a barebones version of the an app that we could run where it still reproduces would be really helpful. Or even if you can get a repro in a CodeSandbox app?
I know you've already listed the extensions you've installed, but just to confirm, you only have 1 copy of React Developer Tools installed, is that correct?
Yes
I'm not sure it is possible to strip project since it is just too big and have too many modules. But you gave me an idea and i tried to run clean npx-create-react-app and it worked. I will try to get more info from my coworkers tomorrow, since i have no info about changes atm and it's too late to ask (it's past work time).
- correct. On your other question around reproducing minimal app, another NDA, that's also actually quite complex, as it's a large mono-repo with aplenty of inter-dependencies, and reproducing such an app to a minimal level is tricky to say the least. I just had a theory that React Dev Tools may now be in conflict with certain node module(s) perhaps, or in conflict with the webpack / typescript transpiled code. It's just a theory. But then with the workaround which works for me and my colleague, the component tree loads again on the target app. I'm not sure what to make of that.
The same issue also occurs on a remote hosted version of the app, which is internal / behind a firewall, not public. So for me, it isn't necessarily narrowed down to a server setup to say.
I forgot about it, same here
Understood that creating a smaller repro is a lot of work, but it needs to be done by someone (either you or us) as part of identifying and fixing a bug. We generally ask that people reporting bugs create the repro because sometimes this reveals an underlying problem in the app/user code itself, but also because you better understand the app (and how to quickly strip unnecessary parts out of it).
- I totally understand your point. Time-permitting, I'll see what i can do. I am thinking of creating a new React app off to scaffold the initial foundations, and then try to mimick as best i can with the organisational setup / configurations, especially the dependencies / compiler / transpiler configurations.
thanks for looking into it and
actually, if you can, one thing we could do to rule out my changes is to do the following: I created a branch where I reverted my changes related to detecting duplicate extensions here: , and I built a version of DevTools with those changes reverted.Could you download this build of DevTools: (or build it yourself off of this ) install it, and check if the problem still reproduces for you? Make sure you've disabled your current version of DevTools before installing this one. In order to install it, you should be able to drag and drop the zip file into . Let me know if you're able to do this and verify that the issue is still occurring?
- look like you've managed to narrow down the root cause to the selective changes around detecting duplicate extensions with which you've reverted to in the test version of the extension. As the described issue no longer persists, and the component tree loads instantly, on both localhost and the internal non-public remotely hosted app Prior to installing your reverted version, i was able to reproduce the issue on the stable release @ , on both environments; local and non-public hosted version of my organisational app. Same issue also resurfaced when i disabled your test version, and re-enabled the stable release version. Hopefully the results of this test will further help isolate the issue.
Same here. I've donwloaded your archive and it worked perfectly. Thanks!
- i was on a lookout for other React websites (after some extensive searching) which emits the same behaviour, and i finally found a React website that you should be able to continuously reproduce the issue against, while using React Dev Tools on the stable version of . The site is a well known public site targeted at Dev / Agile people like us ( ); . Also worthwhile noting that, i managed to apply my to resolve the issue on the above site. So it ticks off the similar behaviours i experienced. Hopefully, this finding will help you in your endeavours and that you'll now be able to debug the issue off the React website alone
Also, i realised i can only reproduce when opening a new tab, and then open React Dev Tools. But then i close Chrome Dev Tools while staying on , and then re-open React Dev Tools, and then the Component Tree loads up this time. Not sure how reliable this method is, but worth pointing out the observation, where opening a new Chrome tab each tab may be a more reliable approach to debug.
- Ok, i've managed to replicate the best workaround solution on my organisations' app too, both on localhost, and non-public hosted versions of the app. Open new Chrome Tab Navigate to troubled site (i.e. my org app, or publicly on ) Open Chrome Dev Tools Open React Dev Tools (stable version @ ) Observe that the component does not load up (just blank) Close Chrome Dev Tools altogether (stay on troubled site in same tab) Re-open Chrome Dev Tools Navigate again to open React Dev Tools Component Tree loads up this time To note again, the above instructions is carried out within the one and only same tab.
thanks for confirming that the issue went away when you installed this version: I'll go ahead and try to get a repro on the Atlassian site
btw , , what version of React are you using?
unfortunately I can't seem to reproduce the issue on What I did: Open a new tab Visit Open Chrome Dev Tools Open Components Tab After doing that the Components tree is always showing up, although sometimes it takes about a second for it to show. Are you always able to consistently reproduce on that site? ! !
14.0

Not 100% reproducible all the time, more like 95%. So i've followed what you've done, and it loads the component tree first time. But then i close that tab, and open a new tab, and follow what you've done again, and this time the Component Tree does not load up. Not sure how many time you've tried. But i assume we're both using latest Chrome, and using React Dev Tools (not your reverted changes version!)
I'll keep trying! and yes I'm using the latest chrome and React Dev Tools 4.20.0 (as I am showing in the screenshot in my comment)
And it looks like is developed on React version . So not sure if you have been trying to repro on this particular version also, locally.
Just to prove that i'm sane (not insane ), here's a GIF screen recording demo i've just recorded, reproducing issue on the public React website !
Scrap the other earlier comment around React versions, as i've just noticed the following public sites that have had no issues on loading the Component Trees first time, are using varying React versions: Netflix @ @ Instagram @
thanks for confirming! quick question, on , did you confirm if the issue also reliably gets fixed with my custom build: ?
When enabled your modded version, disabled stable version, it appears to be reliably fixed 100% of the time. Then when i reverted back the configurations, and what i found with Atlassian site is that it failed to load the component like 25% of the time, while it did load the tree on first load at like 75% of the time from around 20 attempts..
thanks and on your local application it fails 100% of the time when using v4.20.0, correct? I am still unable to reproduce on (and i'm wondering if that might be a separate issue), so i think it would still be helpful if you could provide a small app or code sandbox where the issue reproduces 100% of the time like it does for your app
Yeah, Atlassian could be a separate issue. Haven't retried local application since a few hours or so ago. I'll think about the app mimick-like re-creation, time-permitting of course, also provided that i am even able to provide a reproducible issue from that.
another thing to check is: when the components tree fails to load, do you see any error messages in the console?
-I normally lookout for console errors out of habit, and throughout all occasions when the component tree does not load up, there was no additional logging output to the console, not even errors. Also, by closing and re-opening Chrome Dev Tools, and navigating to React Dev Tools (Component tab) again on second attempt within the same tab, is now the best workaround for now, for me anyway. Talking about console logs, is it possible to recompile a zip binary with additional verbose logging output within the relevant code snippets / areas of concern?
No
For what it's worth, I started having the same issue today. One more detail, when I click on React Developer Tools extension icon in toolbar I'm getting this message: (in case that helps) Refreshing the page helps sometimes, but not always.
thanks for the info is this happening to you 100% of the time? are you also observing that message when hovering on the icon in the toolbar? for context, I'm trying to rule out whether some changes I made to detect duplicate extensions are the root cause of this issue. what's interesting is that those changes would prevent the Components tab from even appearing in DevTools at all (when duplicate installations are present), whereas in this case it's the Components Tree within the Components tab that isn't loading. moreover, this issue of the Components Tree not loading is a long-standing issue that happens sporadically (likely due to a race condition), so i'm not sure if we are mixing up potentially different problems here. interestingly, the originally reported issue does reproduce 100% of the time for and internal apps, so maybe there is something else going on.
Quick favor, could you verify if this build also completely fixes the issue in your local app?: If you can could you verify if either of these 2 builds completely fixes the issue for you?: NOTE: Make sure you've disabled your current version of DevTools before installing these other builds. In order to install it, you should be able to drag and drop the zip file into .
I can't say definitively (not to mislead you), but seems like works for me -- the issue is not appearing. While with ReactDevTools-warning- I'm still experiencing the issue.
apologies for the late reply, had a busy day at work, and after work On the error messages, yes, for some reason it now shows up while still on stable release . The exception reads as below after opening up React Dev Tools on the private remotely hosted app, with the component tree still reliably not loading up first time: Here's the screenshot as proof below: ! Saying that, i opened a new tab on the same url, opened React Dev Tools again, and this time the described exception ( ) is no longer thrown / output to console, while the component tree still failed to load. Guess i was lucky to spot this exception on the previous occasion (as seen on screenshot in this comment). Strange
Oh that's really interesting, thanks for sharing that, I think that might point to why the components tree fails to load even in other cases unrelated to my changes. will look into this a bit
If you can, would you mind trying out this last build and verifying that it reliably fixes the issue on your local apps? I think we narrowed down the cause even a bit further. thanks so much for all your help so far! Also let me know if you see anything logged to the console Again: Make sure you've disabled your current version of DevTools before installing these other builds. In order to install it, you should be able to drag and drop the zip file into .
when i installed this particular custom build (),and disabled the stable build version, i then performed multiple test runs of the local app on a remotely hosted internal site, and i can confirm that the Component Tree loads first time, for the 12 repeated test runs. 100% of the time. In-between the 12 test runs, i quit and restarted Chrome 3 times, and navigated to four different internally remote hosted app environment URLs. Again, each time, the component tree loaded first time without issues. Screenshot of first test run below: !
thanks it's unfortunate that that doesn't seem to line up with testing: let me know if you are able to try out thanks so much again for your help!
Upon installing , and removing / disabling the other versions, i found that after 6 repeated test runs (4 internal remote sites, and restarted Chrome once), the component tree loads up first time each time. Here's a screenshot with all the extra (mostly duplicate) console debugging info output. Note i invoked my own comment so you can tell the logging apart prior and after i opened React Dev Tools (Component tab): ! The logging repeated itself every couple of seconds or so since i opened React Dev Tools. The messages looked liked duplicates to me. Hopefully this will give you more useful info to work with
this is super helpful, thanks!
I'm seeing some unexpected data in those logs, so i have a couple of questions: You said you are using version 4.20.0 of ?Could you open , search for "React", and send me a screenshot of what you see? I'm looking for something like this: !
I just tested ReactDevTools-backend- version and it seem working fine for me! no issues
We run our localhost development build under a regular domain (set via /etc/hosts), and can confirm that while 4.20.0 would always show a blank page under "Components" tab (even after multiple page reloads / browser restarts) and that this build seems to have fixed the issue over multiple tab reloads / browser restarts.
I am indeed using React Dev Tools at stable version from the Chrome Web Store. I attach a screenshot below to prove this, where both our IDs match below. Ignore the other extension , it's absolutely nothing dev related and has been disabled for a long while. !
got it, thanks everyone for the info, that's really helpful!
will close it once the fix from is shipped and verified
Brilliant, and many thanks for your efforts on this fix! Are you in a position to give a rough estimate on when the next build version which includes this fix will be released out into the wild for dev minions like us? I'll also verify the fix when i receive the version update, and post results here.
it takes a few days for the Chrome Web Store to review a new published version, but hopefully within the next few days
just a heads up on this issue, v4.20.1 was finally approved in the Chrome Web Store, and we just submitted v4.20.2 for review, which should include the fix for this issue. i'll comment here again when v4.20.2 is finally out
v4.20.2 which includes this is now published in the Chrome Web Store I'll go ahead and close, but or let me know if you're still having issues (if so we can re-open)
Thanks for the fix. Unfortunately the new version does not work for me and my colleague even though the version you posted above was working after a manual install. Do you have any idea why this might be the case?
hmm thanks do you see any errors in the console when this happens? does it happen consistently? i suspect this might also be the same issue as
I don't see any errors in console. It is completely blank. It does happen consistently on chrome only and localhost only.
Sadly updating to v4.20.2- didn't fix the issue for me either. I'm running Chrome 95.0.4638.54, however, on Firefox 93.0 it seems to work fine. On Chrome I don't have any errors in the console, the component tree is just blank.
I still have the same problems: with Chrome (Version 95.0.4638.54 ) and React Dev Tools (Version 4.20.2 (10/25/2021)). It just doesn't show anything in the React Dev Tools when on localhost. No error or logs usually. I managed to display 1 error just once: <img width="547" alt="Screenshot 2021-10-27 at 15 02 14" src="https://user-"That makes this thing possibly related with but most of the times it's just blank and no errors are shown. Dismissing the error, when it appears, loads successfully the components tree though.
@ - Hi again, so my React Dev Tools Chrome extension updated to , and sadly for some reason, this didn't resolve the issue, on localhost, and on a private remotely hosted URL of app. Also, no new / unrecognised errors were personally observed within the console .. Although, i am still able to apply the workaround of re-opening Chrome Dev Tools React Dev Tools for the second time, and then voila, the Component Tree loads.
thanks for all the reports everyone! that's unfortunate :( that version contains the same fix as the custom build i shared here that seemed to fix the issue 100% of the time. I'm going to look more into this and keep you posted. thanks!
could i ask for another favor? when this happens to you, could you do the following: Detach Chrome Dev Tools itself into a separate window. On the Chrome Dev Tools window, press . This should bring up another dev tools window which is inspecting dev tools itself. On the new dev tools window, do you see any errors?
I've been having the same issues (zipped extension w/fix worked for me but 4.20.2 doesn't) I'm seeing a bunch of these errors with different node numbers in the dev console console: And then a bunch of similar warnings:
Aha. I never knew about this internal self-inspecting Chrome Dev Tools window. So upon carrying out the above instructions, i also appear to be getting similar errors each time the component tree fails to load. The errors consistently appear whenever the component tree fails to load, within the self-inspecting Chrome Dev Tools ( + + ). ! Sometimes, i see 1, or 2, or 3 instances of the tens of duplicate error messages: ! Also, as a sidenote, i noticed as of this morning, that the component tree loads only like ~5% of the time, first time on a localhost version of the app. But when testing on a remotely hosted version of the app, the component tree loads around ~75% of the time. It's very inconsistent. Not sure if this tidbit will aid your investigation. React Dev Tools: Chrome: Mac OS:
I just wanted to inform that v4.20.2 didn't solve this issue for me either (I created the issue that was closed and merged into this one). My problems are similar but not exactly the same as others report: First I get an blank components devtools (only localhost) but when picking select element arrow and hover over elements a lot of errors like this one shows up in the console: Uncaught Error: Could not find ID for Fiber "Grid" at getFiberIDThrows () at Object.getFiberIDForNative () at OverlayOverlay.inspect () at showOverlay () at onPointerOver () React - 16.8.6 Not sure if relevant but: react-scripts 4.0.3
We're shipping another version v4.21.0 to the web store which we think should address this (or reduce the amount of times it triggers ). It should be available in chrome in a few days.
version appears to have resolved the issue Managed to reliably load up the component tree on first load 100% of the time, after repeatedly closing and re-opening tab, and then opening dev tools component tab, for like 20 times across localhost, and remotely hosted sites of the local app, with 2 Chrome restarts in-between to mix things up. Many thanks for your huge efforts in resolving this issue
I confirm that the problem has been resolved with the last version, many thanks for the great work
FYI v4.21.0 is now on Chrome Web Store which should resolve or at least reduce the occurrence of this issue. If you keep seeing problems let us know and we'll re-open the issue. The root cause of of , which is what happened when this occurred, is still undetermined and needs investigation
I'm still experiencing the issue I updated DevTools to 4.21.0 and my Chrome is 95.0.4638.69 - the browser is managed by my company. On localhost the section is either blank or loads but does not update when something changes on the page. Everything works on websites like Also, from time to time when I hit it logs an error like the ones mentioned by other users.
Just to confirm– this happen consistently for you on your website (running on localhost)? it happen for any other websites? (What about your website deployed externally)? Any repro info you can share with us? (Can we run your website locally?)
, it stopped working about 2 weeks ago (at least that's when I noticed) and I haven't seen it working since then works fine on any other website, also on deployed version on the website I am working on. Unfortunately I cannot share it as it's only for users who bought the product. However, I can try creating a basic CRA app and see what happens.
let's continue the conversation in which is a more general version of this issue

// Running module factories is intentionally delayed until we know the hook exists. // This is to avoid issues like: https://github.com/facebook/react-devtools/issues/1039 <del> /** @flow */ </del> <ins> // @flow strict-local </ins> 'use strict';

) { return; } <ins> const extensionId = event.data.extensionId; </ins> window.removeEventListener('message', welcome); <del> setup(window.__REACT_DEVTOOLS_GLOBAL_HOOK__); </del> <ins> setup(window.__REACT_DEVTOOLS_GLOBAL_HOOK__, extensionId); </ins> } window.addEventListener('message', welcome); <del> function setup(hook) { </del> <ins> function setup(hook, extensionId) { </ins> if (hook == null) { // DevTools didn't get injected into this page (maybe b'c of the contentType). return;

{ source: 'react-devtools-bridge', payload: {event, payload}, <ins> extensionId, </ins> }, '*', transferable,

'use strict'; <ins> import {CURRENT_EXTENSION_ID} from './constants'; </ins> let backendDisconnected: boolean = false; let backendInitialized: boolean = false;

{ source: 'react-devtools-content-script', hello: true, <ins> extensionId: CURRENT_EXTENSION_ID, </ins> }, '*', );

{ source: 'react-devtools-content-script', payload: message, <ins> extensionId: CURRENT_EXTENSION_ID, </ins> }, '*', );

type: 'event', event: 'shutdown', }, <ins> extensionId: CURRENT_EXTENSION_ID, </ins> }, '*', );

if (source !== window || !data) { return; } <del> if (data.extensionId !== CURRENT_EXTENSION_ID) { </del> <ins> if (data.extensionId != null && data.extensionId !== CURRENT_EXTENSION_ID) { </ins> if (__DEBUG__) { console.log( `[injectGlobalHook] Received message '${data.source}' from different extension instance. Skipping message.`, { currentExtension: EXTENSION_INSTALLATION_TYPE, <ins> currentExtensionId: CURRENT_EXTENSION_ID, providedExtensionId: data.extensionId, </ins> }, ); }


Question:
a website that uses React. an element that uses Hooks. to load hook names. hook names always fails: !
Fix landed in , it should be a few days before it can be published to the Chrome Web Store, since it needs to go through the review process.

chrome.devtools.inspectedWindow.eval( `window.postMessage({ source: 'react-devtools-inject-backend', <del> extensionId: "${CURRENT_EXTENSION_ID}" </del> <ins> extensionId: "${CURRENT_EXTENSION_ID}", </ins> }, '*');`, function(response, evalError) { if (evalError) {

chrome.runtime.onMessage.addListener(onPortMessage); chrome.devtools.inspectedWindow.eval(` <del> window.postMessage({ source: 'react-devtools-extension', extensionId: "${CURRENT_EXTENSION_ID}" payload: { type: 'fetch-file-with-cache', url: "${url}", }, }); `); </del> <ins> window.postMessage({ source: 'react-devtools-extension', extensionId: "${CURRENT_EXTENSION_ID}", payload: { type: 'fetch-file-with-cache', url: "${url}", }, }, '*'); `); </ins> }; // Fetching files from the extension won't make use of the network cache


Question: This feature is meant to warn about sync priority updates that block paint (e.g. set state in layout effect) but it appears to also warn for transition priority updates. We should fix this.

); } }); <ins> it('should not warn about transition updates scheduled during commit phase', async () => { function Component() { const [value, setValue] = React.useState(0); // eslint-disable-next-line no-unused-vars const [isPending, startTransition] = React.useTransition(); Scheduler.unstable_yieldValue( `Component rendered with value ${value}`, ); // Fake a long render if (value !== 0) { Scheduler.unstable_yieldValue('Long render'); startTime += 20000; } React.useLayoutEffect(() => { startTransition(() => { setValue(1); }); }, []); return value; } if (gate(flags => flags.enableSchedulingProfiler)) { const cpuProfilerSample = creactCpuProfilerSample(); const root = ReactDOM.createRoot(document.createElement('div')); act(() => { root.render(<Component />); }); expect(Scheduler).toHaveYielded([ 'Component rendered with value 0', 'Component rendered with value 0', 'Component rendered with value 1', 'Long render', ]); const testMarks = []; clearedMarks.forEach(markName => { if (markName === '--component-render-start-Component') { // Fake a long running render startTime += 20000; } testMarks.push({ pid: ++pid, tid: ++tid, ts: ++startTime, args: {data: {}}, cat: 'blink.user_timing', name: markName, ph: 'R', }); }); const data = await preprocessData([ cpuProfilerSample, ...createBoilerplateEntries(), ...testMarks, ]); data.schedulingEvents.forEach(event => { expect(event.warning).toBeNull(); }); } }); it('should not warn about deferred value updates scheduled during commit phase', async () => { function Component() { const [value, setValue] = React.useState(0); const deferredValue = React.useDeferredValue(value); Scheduler.unstable_yieldValue( `Component rendered with value ${value} and deferredValue ${deferredValue}`, ); // Fake a long render if (deferredValue !== 0) { Scheduler.unstable_yieldValue('Long render'); startTime += 20000; } React.useLayoutEffect(() => { setValue(1); }, []); return value + deferredValue; } if (gate(flags => flags.enableSchedulingProfiler)) { const cpuProfilerSample = creactCpuProfilerSample(); const root = ReactDOM.createRoot(document.createElement('div')); act(() => { root.render(<Component />); }); expect(Scheduler).toHaveYielded([ 'Component rendered with value 0 and deferredValue 0', 'Component rendered with value 1 and deferredValue 0', 'Component rendered with value 1 and deferredValue 1', 'Long render', ]); const testMarks = []; clearedMarks.forEach(markName => { if (markName === '--component-render-start-Component') { // Fake a long running render startTime += 20000; } testMarks.push({ pid: ++pid, tid: ++tid, ts: ++startTime, args: {data: {}}, cat: 'blink.user_timing', name: markName, ph: 'R', }); }); const data = await preprocessData([ cpuProfilerSample, ...createBoilerplateEntries(), ...testMarks, ]); data.schedulingEvents.forEach(event => { expect(event.warning).toBeNull(); }); } }); </ins> }); describe('errors thrown while rendering', () => {

// See how long the subsequent batch of React work was. const [startTime, stopTime] = getBatchRange(batchUID, profilerData); if (stopTime - startTime > NESTED_UPDATE_DURATION_THRESHOLD) { <del> schedulingEvent.warning = WARNING_STRINGS.NESTED_UPDATE; </del> <ins> // Don't warn about transition updates scheduled during the commit phase. // e.g. useTransition, useDeferredValue // These are allowed to be long-running. if ( !schedulingEvent.lanes.some( lane => profilerData.laneToLabelMap.get(lane) === 'Transition', ) ) { schedulingEvent.warning = WARNING_STRINGS.NESTED_UPDATE; } </ins> } }); state.potentialSuspenseEventsOutsideOfTransition.forEach(