Skip to content

Commit

Permalink
fix[devtools]: check if fiber is unmounted before trying to highlight (
Browse files Browse the repository at this point in the history
…facebook#26983)

For React Native environment, we sometimes spam the console with
warnings `"Could not find Fiber with id ..."`.

This is an attempt to fix this or at least reduce the amount of such
potential warnings being thrown.

Now checking if fiber is already unnmounted before trying to get native
nodes for fiber. This might happen if you try to inspect an element in
DevTools, but at the time when event has been received, the element was
already unmounted.
  • Loading branch information
hoxyq authored and AndyPengc12 committed Apr 15, 2024
1 parent 22b81a0 commit a1ba33f
Show file tree
Hide file tree
Showing 4 changed files with 26 additions and 19 deletions.
5 changes: 5 additions & 0 deletions packages/react-devtools-shared/src/backend/legacy/renderer.js
Original file line number Diff line number Diff line change
Expand Up @@ -1101,6 +1101,10 @@ export function attach(

function unpatchConsoleForStrictMode() {}

function hasFiberWithId(id: number): boolean {
return idToInternalInstanceMap.has(id);
}

return {
clearErrorsAndWarnings,
clearErrorsForFiberID,
Expand All @@ -1124,6 +1128,7 @@ export function attach(
handleCommitFiberRoot,
handleCommitFiberUnmount,
handlePostCommitFiberRoot,
hasFiberWithId,
inspectElement,
logElementToConsole,
overrideError,
Expand Down
23 changes: 9 additions & 14 deletions packages/react-devtools-shared/src/backend/renderer.js
Original file line number Diff line number Diff line change
Expand Up @@ -2736,21 +2736,11 @@ export function attach(

function findNativeNodesForFiberID(id: number) {
try {
let fiber = findCurrentFiberUsingSlowPathById(id);
const fiber = findCurrentFiberUsingSlowPathById(id);
if (fiber === null) {
return null;
}
// Special case for a timed-out Suspense.
const isTimedOutSuspense =
fiber.tag === SuspenseComponent && fiber.memoizedState !== null;
if (isTimedOutSuspense) {
// A timed-out Suspense's findDOMNode is useless.
// Try our best to find the fallback directly.
const maybeFallbackFiber = fiber.child && fiber.child.sibling;
if (maybeFallbackFiber != null) {
fiber = maybeFallbackFiber;
}
}

const hostFibers = findAllCurrentHostFibers(id);
return hostFibers.map(hostFiber => hostFiber.stateNode).filter(Boolean);
} catch (err) {
Expand All @@ -2759,9 +2749,9 @@ export function attach(
}
}

function getDisplayNameForFiberID(id: number) {
function getDisplayNameForFiberID(id: number): null | string {
const fiber = idToArbitraryFiberMap.get(id);
return fiber != null ? getDisplayNameForFiber(((fiber: any): Fiber)) : null;
return fiber != null ? getDisplayNameForFiber(fiber) : null;
}

function getFiberForNative(hostInstance: NativeType) {
Expand Down Expand Up @@ -4456,6 +4446,10 @@ export function attach(
traceUpdatesEnabled = isEnabled;
}

function hasFiberWithId(id: number): boolean {
return idToArbitraryFiberMap.has(id);
}

return {
cleanup,
clearErrorsAndWarnings,
Expand All @@ -4476,6 +4470,7 @@ export function attach(
handleCommitFiberRoot,
handleCommitFiberUnmount,
handlePostCommitFiberRoot,
hasFiberWithId,
inspectElement,
logElementToConsole,
patchConsoleForStrictMode,
Expand Down
1 change: 1 addition & 0 deletions packages/react-devtools-shared/src/backend/types.js
Original file line number Diff line number Diff line change
Expand Up @@ -379,6 +379,7 @@ export type RendererInterface = {
handleCommitFiberRoot: (fiber: Object, commitPriority?: number) => void,
handleCommitFiberUnmount: (fiber: Object) => void,
handlePostCommitFiberRoot: (fiber: Object) => void,
hasFiberWithId: (id: number) => boolean,
inspectElement: (
requestID: number,
id: number,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,15 +104,21 @@ export default function setupHighlighter(
const renderer = agent.rendererInterfaces[rendererID];
if (renderer == null) {
console.warn(`Invalid renderer id "${rendererID}" for element "${id}"`);

hideOverlay(agent);
return;
}

let nodes: ?Array<HTMLElement> = null;
if (renderer != null) {
nodes = ((renderer.findNativeNodesForFiberID(
id,
): any): ?Array<HTMLElement>);
// In some cases fiber may already be unmounted
if (!renderer.hasFiberWithId(id)) {
hideOverlay(agent);
return;
}

const nodes: ?Array<HTMLElement> = (renderer.findNativeNodesForFiberID(
id,
): any);

if (nodes != null && nodes[0] != null) {
const node = nodes[0];
// $FlowFixMe[method-unbinding]
Expand Down

0 comments on commit a1ba33f

Please sign in to comment.