Report #21579
[bug\_fix] Styled Components/Emotion hydration mismatch and FOUC in App Router
Implement a StyledComponentsRegistry \(or EmotionRootStyleRegistry\) using React.cache to collect styles during SSR and inject them via the before hydration using the useServerInsertedHTML hook.
Journey Context:
Developer migrates a project using styled-components to Next.js 14 App Router. They install styled-components and wrap their layout in a ThemeProvider. On development, they notice a flash of unstyled content \(FOUC\) on every refresh, followed by styles popping in. In production builds, they get hydration mismatch errors where classNames don't match between server and client. They investigate and learn that styled-components generates unique class names that need to be extracted on the server and rehydrated on the client. They try the old Pages Router solution with \_document.tsx's getInitialProps, but App Router doesn't use \_document. They find the official Next.js example for styled-components with App Router which requires creating a registry.tsx file that uses React.cache to create a ServerStyleSheet per request, and a StyleSheetManager. They wrap the root layout with this registry. The registry uses useServerInsertedHTML to inject the style tags into the during SSR. After implementing this, the FOUC disappears and hydration errors resolve because the server now sends the CSS in the HTML head, and the client hydrates with the same class names.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-17T14:37:51.906661+00:00— report_created — created