Skip to content

[tabs][slider] Skip client-only prehydration scripts#4530

Merged
atomiks merged 5 commits intomui:masterfrom
atomiks:codex/avoid-client-only-prehydration-scripts
Apr 7, 2026
Merged

[tabs][slider] Skip client-only prehydration scripts#4530
atomiks merged 5 commits intomui:masterfrom
atomiks:codex/avoid-client-only-prehydration-scripts

Conversation

@atomiks
Copy link
Copy Markdown
Contributor

@atomiks atomiks commented Apr 6, 2026

Fixes #4373

This avoids rendering Base UI's pre-hydration inline scripts when a component is mounting client-side instead of hydrating server-rendered markup. The key nuance is that isMounted is not enough here: on a Next.js client transition the first client render still has isMounted === false, so the old logic continued to render the script and trigger the warning. useIsHydrating fixes that by distinguishing SSR hydration from a fresh client-only mount.

Changes

  • Add a small internal hydration hook that returns true only during SSR hydration.
  • Gate Tabs.Indicator and Slider edge-aligned pre-hydration behavior on hydration instead of mount state.
  • Remove the now-redundant mount checks from the affected Tabs and Slider paths.
  • Add regression tests for the hydration hook and SSR coverage for the pre-hydration script paths.

@atomiks atomiks added type: bug It doesn't behave as expected. component: tabs Changes related to the tabs component. component: slider Changes related to the slider component. integration: nextjs Next.js labels Apr 6, 2026 — with ChatGPT Codex Connector
@pkg-pr-new
Copy link
Copy Markdown

pkg-pr-new bot commented Apr 6, 2026

commit: 2325b2d

@mui-bot
Copy link
Copy Markdown

mui-bot commented Apr 6, 2026

Bundle size report

Bundle Parsed size Gzip size
@base-ui/react 🔺+30B(+0.01%) 🔺+42B(+0.03%)

Details of bundle changes


Check out the code infra dashboard for more information about this PR.

@netlify
Copy link
Copy Markdown

netlify bot commented Apr 6, 2026

Deploy Preview for base-ui ready!

Name Link
🔨 Latest commit 2325b2d
🔍 Latest deploy log https://app.netlify.com/projects/base-ui/deploys/69d495f787dfc20008cb432c
😎 Deploy Preview https://deploy-preview-4530--base-ui.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@atomiks atomiks marked this pull request as ready for review April 6, 2026 02:35
Copy link
Copy Markdown
Contributor Author

atomiks commented Apr 6, 2026

Codex Review (GPT-5.4)

This is a bug-fix PR with tests and react-ui as the main secondary tags. The branch now fixes the real regression boundary cleanly: it switches the guard from “has this component mounted yet?” to “is this render actually hydrating SSR markup?”, which is the distinction Next.js 16.2.x exposed.

1. Bugs / Issues (None)

2. Root Cause & Patch Assessment

The final shape looks correct to me. The old isMounted checks were answering the wrong question for Next client transitions, because a fresh client-side mount still starts with isMounted === false; that meant the inline pre-hydration scripts still rendered during client navigation and triggered the warning.

Using a shared useIsHydrating() hook is a better root-cause fix because it narrows the behavior to actual SSR hydration only. I also like that the follow-up simplification removed the now-redundant mount bookkeeping instead of leaving both concepts in place and making the condition harder to reason about.

3. Pattern Consistency Assessment

The consistency pass across the affected Slider paths was worthwhile. Updating SliderIndicator alongside SliderThumb keeps the inset pre-hydration behavior aligned, so client-only mounts no longer carry the temporary “pretend we are still pre-hydration” hiding logic in one place but not the other.

The new helper is also appropriately small and private. Reusing NOOP for the subscribe cleanup keeps it aligned with existing repo conventions without adding extra indirection.

4. Test Coverage Assessment

The regression coverage now matches the change well enough for a bug-fix PR of this size. In particular, the branch adds:

  • direct hook-level coverage for SSR hydration vs client-only mount behavior
  • SSR coverage that the inline pre-hydration script is still emitted where required
  • preservation of the existing Slider positioning assertion, with the edge-thumb script case split into its own test

I also rechecked the targeted validation that matters for the touched paths:

  • pnpm test:jsdom useIsHydrating --no-watch
  • pnpm test:jsdom TabsIndicator --no-watch
  • pnpm test:jsdom SliderThumb --no-watch
  • pnpm test:chromium TabsIndicator --no-watch
  • pnpm test:chromium SliderThumb --no-watch
  • pnpm eslint ... on the touched files
  • pnpm typescript

I additionally verified the PR-published package itself via pnpm add https://pkg.pr.new/mui/base-ui/@base-ui/react@4530 in fresh App Router repro apps on Next 16.1.7, 16.2.0, and 16.2.2 (with the matching @base-ui/utils@4530 package). The result matched the intended fix exactly:

  • direct loads logged no warning in all cases
  • client-side navigation still logged the warning for a plain literal <script> in Next 16.2.0 and 16.2.2, confirming the repro environment was valid
  • client-side navigation logged no warning for the Base UI Tabs.Indicator renderBeforeHydration repro or the Slider.Root thumbAlignment="edge" repro with the PR package installed

That external-package check is especially useful here because it confirms the fix is not just correct in the local workspace build, but also in the actual package artifact reviewers and downstream users would install.

Recommendation

Approve ✅

I don’t see any remaining correctness issues in the final branch. The patch now fixes the actual hydration-vs-client-mount distinction, applies that reasoning consistently to the affected Slider/Tabs paths, and now has both focused in-repo regression coverage and a fresh Next.js external-package repro confirming the published PR artifact eliminates the warning without masking the underlying Next regression.

@atomiks atomiks merged commit bffbfcb into mui:master Apr 7, 2026
23 checks passed
@atomiks atomiks deleted the codex/avoid-client-only-prehydration-scripts branch April 7, 2026 05:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

component: slider Changes related to the slider component. component: tabs Changes related to the tabs component. integration: nextjs Next.js type: bug It doesn't behave as expected.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[slider] Next.js script tag error on slider thumb

2 participants