Skip to content

[Fiber] Double invoke Effects in Strict Mode during Hydration#658

Open
everettbu wants to merge 2 commits into
mainfrom
sebbie/se-hydration
Open

[Fiber] Double invoke Effects in Strict Mode during Hydration#658
everettbu wants to merge 2 commits into
mainfrom
sebbie/se-hydration

Conversation

@everettbu

Copy link
Copy Markdown

Mirror of facebook/react#35961
Original author: eps1lon


Summary

Also reported in vercel/next.js#66210

Not double invoking during Hydration was on oversight. Double invoking during Hydration ensures parity between hydrateRoot and createRoot.

Double invoking an Effect is tracked with PlacementDEV. This was always used together with Placement. However, during hydration we don't track side-effects i.e. set no Placement flag causing no double invocation of Effects in Strict Mode.

Now we set PlacementDEV when we set the Hydration flag to double invoke Effects in Strict Mode when we hydrated which is conceptually like a Placement during client-render.

How did you test this change?

  • Added test (see first commit for previous behavior)
  • Added a regression test for Activity which didn't change in behavior

@everettbu everettbu added CLA Signed React Core Team Opened by a member of the React Core Team labels Mar 5, 2026
@greptile-apps

greptile-apps Bot commented Mar 5, 2026

Copy link
Copy Markdown

Greptile Summary

This PR fixes an oversight where Strict Mode was not double-invoking effects during hydration, breaking the expected parity between hydrateRoot and createRoot. The fix adds the PlacementDEV flag alongside the Hydrating flag in three hydration code paths (HostRoot, Suspense, and Activity), and extends the OffscreenComponent check in doubleInvokeEffectsInDEVIfNecessary to also consider PlacementDEV.

  • Adds PlacementDEV flag in ReactFiberBeginWork.js at the three locations where Hydrating is set: host root children, dehydrated Suspense boundaries, and dehydrated Activity components
  • Updates ReactFiberWorkLoop.js to trigger double invocation on visible Offscreen/Activity fibers that have PlacementDEV set (newly hydrated), not just those with Visibility changes
  • Adds tests for basic hydration effect replay, suspended boundary hydration effect replay, and an Activity regression test confirming existing behavior for newly inserted children

Confidence Score: 5/5

  • This PR is safe to merge — it's a well-scoped bug fix with comprehensive test coverage and no production behavior changes.
  • The change is minimal, targeted, and follows established patterns already used in ReactChildFiber.js. PlacementDEV is only read inside DEV guards, so there is zero production impact. The fix correctly addresses all three hydration paths (HostRoot, Suspense, Activity) and includes tests for each scenario. The Activity test is a regression test confirming no behavior change.
  • No files require special attention

Important Files Changed

Filename Overview
packages/react-reconciler/src/ReactFiberBeginWork.js Adds PlacementDEV flag alongside Hydrating in three hydration paths (Activity, HostRoot, Suspense) to enable Strict Mode double-invocation of effects during hydration. Consistent with existing patterns in ReactChildFiber.js.
packages/react-reconciler/src/ReactFiberWorkLoop.js Extends the OffscreenComponent check in doubleInvokeEffectsInDEVIfNecessary to also trigger on PlacementDEV (not just Visibility), ensuring newly hydrated Offscreen components also get their effects double-invoked.
packages/react-dom/src/tests/ReactServerRenderingHydration-test.js Adds test verifying effects are double-invoked (mount, unmount, mount) in DEV mode when hydrating a StrictMode subtree. Correct assertions for both DEV and production.
packages/react-dom/src/tests/ReactDOMServerPartialHydration-test.internal.js Adds test for effect replay when a suspended Suspense boundary hydrates in StrictMode. Uses React.use with a promise to simulate deferred hydration. Correct expected behavior for DEV and production.
packages/react-reconciler/src/tests/ActivityStrictMode-test.js Adds regression test for Activity (Offscreen) StrictMode behavior: verifies newly inserted children get double-invoked effects while existing children don't, across multiple render scenarios. No behavior change, only test coverage.

Last reviewed commit: 8975211

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CLA Signed React Core Team Opened by a member of the React Core Team

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants