@samitouri / QOS-React-2 / commits / 794b770dbd

fix[devtools]: check if fiber is unmounted before trying to highlight (#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.

Ruslan Lesiutin committed Jun 22, 2023 at 08:51 UTC 794b770dbd6be48d42438ea76911d32c37c7dd6e
4 files changed +26 -19
packages/react-devtools-shared/src/backend/legacy/renderer.js
+5
@@ -1101,6 +1101,10 @@ export function attach(
1101
1102 function unpatchConsoleForStrictMode() {}
1103
1104 + function hasFiberWithId(id: number): boolean {
1105 + return idToInternalInstanceMap.has(id);
1106 + }
1107 +
1108 return {
1109 clearErrorsAndWarnings,
1110 clearErrorsForFiberID,
@@ -1124,6 +1128,7 @@ export function attach(
1128 handleCommitFiberRoot,
1129 handleCommitFiberUnmount,
1130 handlePostCommitFiberRoot,
1131 + hasFiberWithId,
1132 inspectElement,
1133 logElementToConsole,
1134 overrideError,
packages/react-devtools-shared/src/backend/renderer.js
+9 -14
@@ -2736,21 +2736,11 @@ export function attach(
2736
2737 function findNativeNodesForFiberID(id: number) {
2738 try {
2739 - let fiber = findCurrentFiberUsingSlowPathById(id);
2739 + const fiber = findCurrentFiberUsingSlowPathById(id);
2740 if (fiber === null) {
2741 return null;
2742 }
2743 - // Special case for a timed-out Suspense.
2744 - const isTimedOutSuspense =
2745 - fiber.tag === SuspenseComponent && fiber.memoizedState !== null;
2746 - if (isTimedOutSuspense) {
2747 - // A timed-out Suspense's findDOMNode is useless.
2748 - // Try our best to find the fallback directly.
2749 - const maybeFallbackFiber = fiber.child && fiber.child.sibling;
2750 - if (maybeFallbackFiber != null) {
2751 - fiber = maybeFallbackFiber;
2752 - }
2753 - }
2743 +
2744 const hostFibers = findAllCurrentHostFibers(id);
2745 return hostFibers.map(hostFiber => hostFiber.stateNode).filter(Boolean);
2746 } catch (err) {
@@ -2759,9 +2749,9 @@ export function attach(
2749 }
2750 }
2751
2762 - function getDisplayNameForFiberID(id: number) {
2752 + function getDisplayNameForFiberID(id: number): null | string {
2753 const fiber = idToArbitraryFiberMap.get(id);
2764 - return fiber != null ? getDisplayNameForFiber(((fiber: any): Fiber)) : null;
2754 + return fiber != null ? getDisplayNameForFiber(fiber) : null;
2755 }
2756
2757 function getFiberForNative(hostInstance: NativeType) {
@@ -4456,6 +4446,10 @@ export function attach(
4446 traceUpdatesEnabled = isEnabled;
4447 }
4448
4449 + function hasFiberWithId(id: number): boolean {
4450 + return idToArbitraryFiberMap.has(id);
4451 + }
4452 +
4453 return {
4454 cleanup,
4455 clearErrorsAndWarnings,
@@ -4476,6 +4470,7 @@ export function attach(
4470 handleCommitFiberRoot,
4471 handleCommitFiberUnmount,
4472 handlePostCommitFiberRoot,
4473 + hasFiberWithId,
4474 inspectElement,
4475 logElementToConsole,
4476 patchConsoleForStrictMode,
packages/react-devtools-shared/src/backend/types.js
+1
@@ -379,6 +379,7 @@ export type RendererInterface = {
379 handleCommitFiberRoot: (fiber: Object, commitPriority?: number) => void,
380 handleCommitFiberUnmount: (fiber: Object) => void,
381 handlePostCommitFiberRoot: (fiber: Object) => void,
382 + hasFiberWithId: (id: number) => boolean,
383 inspectElement: (
384 requestID: number,
385 id: number,
packages/react-devtools-shared/src/backend/views/Highlighter/index.js
+11 -5
@@ -104,15 +104,21 @@ export default function setupHighlighter(
104 const renderer = agent.rendererInterfaces[rendererID];
105 if (renderer == null) {
106 console.warn(`Invalid renderer id "${rendererID}" for element "${id}"`);
107 +
108 + hideOverlay(agent);
109 + return;
110 }
111
109 - let nodes: ?Array<HTMLElement> = null;
110 - if (renderer != null) {
111 - nodes = ((renderer.findNativeNodesForFiberID(
112 - id,
113 - ): any): ?Array<HTMLElement>);
112 + // In some cases fiber may already be unmounted
113 + if (!renderer.hasFiberWithId(id)) {
114 + hideOverlay(agent);
115 + return;
116 }
117
118 + const nodes: ?Array<HTMLElement> = (renderer.findNativeNodesForFiberID(
119 + id,
120 + ): any);
121 +
122 if (nodes != null && nodes[0] != null) {
123 const node = nodes[0];
124 // $FlowFixMe[method-unbinding]