Skip to content

Commit 64740e0

Browse files
committed
[Fiber] Double invoke Effects in Strict Mode during Hydration
1 parent 5de5395 commit 64740e0

4 files changed

Lines changed: 27 additions & 7 deletions

File tree

packages/react-dom/src/__tests__/ReactDOMServerPartialHydration-test.internal.js

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -316,7 +316,14 @@ describe('ReactDOMServerPartialHydration', () => {
316316

317317
expect(container.textContent).toBe('Hello');
318318
if (__DEV__) {
319-
expect(log).toEqual(['layout mount', 'effect mount']);
319+
expect(log).toEqual([
320+
'layout mount',
321+
'effect mount',
322+
'layout unmount',
323+
'effect unmount',
324+
'layout mount',
325+
'effect mount',
326+
]);
320327
} else {
321328
expect(log).toEqual(['layout mount', 'effect mount']);
322329
}

packages/react-dom/src/__tests__/ReactServerRenderingHydration-test.js

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -429,7 +429,14 @@ describe('ReactDOMServerHydration', () => {
429429
});
430430

431431
if (__DEV__) {
432-
expect(log).toEqual(['layout mount', 'effect mount']);
432+
expect(log).toEqual([
433+
'layout mount',
434+
'effect mount',
435+
'layout unmount',
436+
'effect unmount',
437+
'layout mount',
438+
'effect mount',
439+
]);
433440
} else {
434441
expect(log).toEqual(['layout mount', 'effect mount']);
435442
}

packages/react-reconciler/src/ReactFiberBeginWork.js

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ import {
8888
NoFlags,
8989
PerformedWork,
9090
Placement,
91+
PlacementDEV,
9192
Hydrating,
9293
Callback,
9394
ContentReset,
@@ -1080,7 +1081,8 @@ function updateDehydratedActivityComponent(
10801081
// Conceptually this is similar to Placement in that a new subtree is
10811082
// inserted into the React tree here. It just happens to not need DOM
10821083
// mutations because it already exists.
1083-
primaryChildFragment.flags |= Hydrating;
1084+
// We should still treat it as a newly inserted Fiber to double invoke Strict Effects.
1085+
primaryChildFragment.flags |= Hydrating | PlacementDEV;
10841086
return primaryChildFragment;
10851087
}
10861088
} else {
@@ -1896,7 +1898,8 @@ function updateHostRoot(
18961898
// Conceptually this is similar to Placement in that a new subtree is
18971899
// inserted into the React tree here. It just happens to not need DOM
18981900
// mutations because it already exists.
1899-
node.flags = (node.flags & ~Placement) | Hydrating;
1901+
// We should still treat it as a newly inserted Fiber to double invoke Strict Effects.
1902+
node.flags = (node.flags & ~Placement) | Hydrating | PlacementDEV;
19001903
node = node.sibling;
19011904
}
19021905
}
@@ -3101,7 +3104,8 @@ function updateDehydratedSuspenseComponent(
31013104
// Conceptually this is similar to Placement in that a new subtree is
31023105
// inserted into the React tree here. It just happens to not need DOM
31033106
// mutations because it already exists.
3104-
primaryChildFragment.flags |= Hydrating;
3107+
// We should still treat it as a newly inserted Fiber to double invoke Strict Effects.
3108+
primaryChildFragment.flags |= Hydrating | PlacementDEV;
31053109
return primaryChildFragment;
31063110
}
31073111
} else {

packages/react-reconciler/src/ReactFiberWorkLoop.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5255,9 +5255,11 @@ function doubleInvokeEffectsInDEVIfNecessary(
52555255
if (fiber.memoizedState === null) {
52565256
// Only consider Offscreen that is visible.
52575257
// TODO (Offscreen) Handle manual mode.
5258-
if (isInStrictMode && fiber.flags & Visibility) {
5259-
// Double invoke effects on Offscreen's subtree only
5258+
if (isInStrictMode && fiber.flags & (Visibility | PlacementDEV)) {
5259+
// Double invoke effects on Offscreen's subtree
52605260
// if it is visible and its visibility has changed.
5261+
// However, we also need to consider newly hydrated Offscreen because their
5262+
// visibility flags might not have changed.
52615263
runWithFiberInDEV(fiber, doubleInvokeEffectsOnFiber, root, fiber);
52625264
} else if (fiber.subtreeFlags & PlacementDEV) {
52635265
// Something in the subtree could have been suspended.

0 commit comments

Comments
 (0)