Skip to content

Replace Suspense hydration pattern with useEffect in ThemeSelector#57

Merged
jalexw merged 1 commit into
mainfrom
claude/fix-themeselector-prerender-FHFWq
May 20, 2026
Merged

Replace Suspense hydration pattern with useEffect in ThemeSelector#57
jalexw merged 1 commit into
mainfrom
claude/fix-themeselector-prerender-FHFWq

Conversation

@jalexw
Copy link
Copy Markdown
Contributor

@jalexw jalexw commented May 20, 2026

Summary

Refactored the ThemeSelector component to use a useEffect-based hydration pattern instead of React Suspense. This eliminates the need for Suspense boundaries and their fallback components while maintaining the same server/client hydration safety.

Key Changes

  • Replaced Suspense pattern with useHasMounted() hook: Created a new custom hook that uses useState and useEffect to track client-side mounting, replacing the previous promise-based getHydrationPromise() approach
  • Removed fallback components: Deleted SegmentedThemeSelectorFallback and CompactThemeSelectorFallback as their logic is now integrated directly into the main components
  • Inlined fallback UI: Both SegmentedThemeSelector and CompactThemeSelector now conditionally render disabled/inert controls during the initial render (before useEffect runs), then swap to the real theme-aware UI after mount
  • Simplified component structure: Removed the Suspense wrapper and consolidated the "Content" and "Fallback" component pairs into single unified components
  • Updated JSDoc: Modified the component documentation to reflect the new hydration approach

Implementation Details

The new useHasMounted() hook returns false on the server and during initial client hydration, then true after the first useEffect runs. This ensures:

  • SSR markup renders an inert disabled control
  • Initial client hydration matches the SSR output (no mismatch)
  • After mount, the real theme-aware UI takes over via the effect
  • No unresolved Suspense boundaries remain in the tree (fixes static prerender issues)

Version bumped to 0.54.2.

https://claude.ai/code/session_01NUbaejFGHF9S2bcVKAZYj8

…ct-driven mounted flag so the component no longer leaves an unresolved Suspense boundary in the SSR/static-prerender output (which was breaking Next.js 16 `next build` for consumers that put ThemeSelector on a statically prerendered route).
@vercel
Copy link
Copy Markdown

vercel Bot commented May 20, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
ui Ready Ready Preview, Comment May 20, 2026 9:20pm

Request Review

@jalexw jalexw merged commit 727f3db into main May 20, 2026
8 checks passed
@jalexw jalexw deleted the claude/fix-themeselector-prerender-FHFWq branch May 20, 2026 21:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants