@samitouri / QOS-React / commits / 2eb3181eb4

fixed unfound node error when Suspense is filtered (#20019)

* fixed unfound node error when Suspense is filtered * added a test for filtered Suspense node

IDrissAitHafid committed Oct 15, 2020 at 19:45 UTC 2eb3181eb4247077eafc4df98d06d7a999ecf5d8
3 files changed +31 -1
packages/react-devtools-shared/src/__tests__/__snapshots__/storeComponentFilters-test.js.snap
+7
@@ -97,6 +97,13 @@ exports[`Store component filters should not break when Suspense nodes are filter
97 <Component>
98 `;
99
100 +exports[`Store component filters should not break when Suspense nodes are filtered from the tree: 3: suspended 1`] = `
101 +[root]
102 + ▾ <Wrapper>
103 + ▾ <Loading>
104 + <div>
105 +`;
106 +
107 exports[`Store component filters should support filtering by element type: 1: mount 1`] = `
108 [root]
109 ▾ <Root>
packages/react-devtools-shared/src/__tests__/storeComponentFilters-test.js
+3
@@ -256,5 +256,8 @@ describe('Store component filters', () => {
256
257 act(() => ReactDOM.render(<Wrapper shouldSuspend={false} />, container));
258 expect(store).toMatchSnapshot('2: resolved');
259 +
260 + act(() => ReactDOM.render(<Wrapper shouldSuspend={true} />, container));
261 + expect(store).toMatchSnapshot('3: suspended');
262 });
263 });
packages/react-devtools-shared/src/backend/renderer.js
+21 -1
@@ -1437,6 +1437,9 @@ export function attach(
1437 }
1438
1439 function recordResetChildren(fiber: Fiber, childSet: Fiber) {
1440 + if (__DEBUG__) {
1441 + debug('recordResetChildren()', childSet, fiber);
1442 + }
1443 // The frontend only really cares about the displayName, key, and children.
1444 // The first two don't really change, so we are only concerned with the order of children here.
1445 // This is trickier than a simple comparison though, since certain types of fibers are filtered.
@@ -1471,6 +1474,23 @@ export function attach(
1474 nextChildren.push(getFiberID(getPrimaryFiber(fiber)));
1475 } else {
1476 let child = fiber.child;
1477 + const isTimedOutSuspense =
1478 + fiber.tag === SuspenseComponent && fiber.memoizedState !== null;
1479 + if (isTimedOutSuspense) {
1480 + // Special case: if Suspense mounts in a timed-out state,
1481 + // get the fallback child from the inner fragment,
1482 + // and skip over the primary child.
1483 + const primaryChildFragment = fiber.child;
1484 + const fallbackChildFragment = primaryChildFragment
1485 + ? primaryChildFragment.sibling
1486 + : null;
1487 + const fallbackChild = fallbackChildFragment
1488 + ? fallbackChildFragment.child
1489 + : null;
1490 + if (fallbackChild !== null) {
1491 + child = fallbackChild;
1492 + }
1493 + }
1494 while (child !== null) {
1495 findReorderedChildrenRecursively(child, nextChildren);
1496 child = child.sibling;
@@ -1592,7 +1612,7 @@ export function attach(
1612 if (nextFallbackChildSet != null) {
1613 mountFiberRecursively(
1614 nextFallbackChildSet,
1595 - nextFiber,
1615 + shouldIncludeInTree ? nextFiber : parentFiber,
1616 true,
1617 traceNearestHostComponentUpdate,
1618 );