Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

docs: add section for FOUC bug in next js 13 #971

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
74 changes: 74 additions & 0 deletions sections/advanced/server-side-rendering.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,80 @@ On this version, you [only need to add](https://github.com/vercel/next.js/blob/c

For routes defined in the `app/` directory, in Next.js v13+, you'll need to put a styled-components registry in one of your layout files, as [described in Next.js docs](https://nextjs.org/docs/app/building-your-application/styling/css-in-js#styled-components). Note that this depends on styled-components v6+. Also note that the `'use client'` directive is used - so while your page will be server-side rendered, styled-components will still appear in your client bundle.

#### Note: When using Next.js 13, you might see a flash of unstyled content (FOUC)

You may experience a flash of unstyled content (FOUC) due to "delay bugs" in client-side rendering. This happens because styled-components' styles are not immediately applied when the page is rendered, causing unstyled elements to appear for a split second.

To resolve this issue, follow these steps:

1. Add the following to your next.config.js file.

```js
/** @type {import('next').NextConfig} */
const nextConfig = {
reactStrictMode: true,
compiler: {
styledComponents: true,
},
}

module.exports = nextConfig
```
2. Create the registry.tsx file with the following code:
```tsx
'use client'

import React, { useState } from 'react';
import { useServerInsertedHTML } from 'next/navigation';
import { ServerStyleSheet, StyleSheetManager } from 'styled-components';

export default function StyledComponentsRegistry({
children,
}: {
children: React.ReactNode
}) {
// Only create stylesheet once with lazy initial state
// x-ref: https://reactjs.org/docs/hooks-reference.html#lazy-initial-state
const [styledComponentsStyleSheet] = useState(() => new ServerStyleSheet())

useServerInsertedHTML(() => {
const styles = styledComponentsStyleSheet.getStyleElement()
styledComponentsStyleSheet.instance.clearTag()
return styles
})

if (typeof window !== 'undefined') return <>{children}</>

return (
<StyleSheetManager sheet={styledComponentsStyleSheet.instance}>
{children}
</StyleSheetManager>
)
};
```

3. Add the ```'use client'``` directive to your layout.tsx file and wrap all the children components on your layout with the StyledComponentsRegistry component.
```tsx
'use client'
import StyledComponentsRegistry from './registry';

export default function RootLayout({
children,
}: {
children: React.ReactNode
}) {
return (
<html lang="en">
<StyledComponentsRegistry>
<body>
{children}
</body>
</StyledComponentsRegistry>
</html>
)
};
```

### Gatsby

[Gatsby](https://www.gatsbyjs.org/) has an official plugin that enables server-side rendering for styled-components.
Expand Down