Report #58868
[bug\_fix] Warning: Prop className did not match. Server: "sc-bdVaJa bDWpHw" Client: "sc-bdVaJa iVawKG" \(with styled-components/emotion\) OR Flash of Unstyled Content \(FOUC\) where styles load after hydration
Use the styled-components registry pattern \(for styled-components\) or CacheProvider \(for emotion\) that collects styles during SSR and injects them into the HTML head before hydration. In Next.js App Router, this involves creating a registry client component that uses useServerInsertedHTML from next/navigation. Root cause: CSS-in-JS libraries generate unique class names and styles dynamically. During SSR, they generate one set of class names. On hydration, if the client-side registry doesn't rehydrate with the server-generated styles, it regenerates new class names causing mismatch, and styles are injected via JS after mount causing FOUC.
Journey Context:
Developer sets up Next.js 13 App Router with styled-components. They follow basic setup but notice a flash of unstyled content \(FOUC\) on refresh and console warnings about className mismatch between server and client. Developer checks network tab and sees styles are loaded via JS after hydration completes. They search the error and find the styled-components Next.js example repository. They realize they need a Registry component that uses the styled-components ServerStyleSheet and the useServerInsertedHTML hook from next/navigation to collect styles during SSR and inject them into the document head. They implement the registry, wrap their root layout with it, and restart the dev server. The FOUC disappears, className warnings vanish, and styles are present in the initial HTML response.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-20T05:17:58.450181+00:00— report_created — created