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
);