-
-
Save zslabs/63350612a94de7d98a4fe7a13306b6cc to your computer and use it in GitHub Desktop.
Styled Components in Remix
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { renderToString } from "react-dom/server"; | |
import { RemixServer } from "remix"; | |
import type { EntryContext } from "remix"; | |
import { ServerStyleSheet } from "styled-components"; | |
import StylesContext from "./StylesContext"; | |
export default function handleRequest( | |
request: Request, | |
responseStatusCode: number, | |
responseHeaders: Headers, | |
remixContext: EntryContext | |
) { | |
const sheet = new ServerStyleSheet(); | |
// Render <body> and extract styles | |
let body = renderToString( | |
sheet.collectStyles( | |
<StylesContext.Provider value={{ styles: [], renderMode: 'body' }}> | |
<RemixServer context={remixContext} url={request.url} /> | |
</StylesContext.Provider> | |
) | |
); | |
// Note: getStyleTags is not really suitable here, using getStyleElement instead | |
let styles = sheet.getStyleElement(); | |
sheet.seal(); | |
// Render <head> with styles extracted from body | |
let head = renderToString( | |
<StylesContext.Provider value={{ styles, renderMode: 'head' }}> | |
<RemixServer | |
context={remixContext} | |
url={request.url} | |
/> | |
</StylesContext.Provider> | |
); | |
let markup = `<!DOCTYPE html><html lang="en">${head}${body}</html>`; | |
responseHeaders.set("Content-Type", "text/html"); | |
return new Response(markup, { | |
status: responseStatusCode, | |
headers: responseHeaders | |
}); | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
... | |
function Document({ | |
children, | |
title, | |
}: { | |
children: React.ReactNode; | |
title?: string; | |
}) { | |
let { styles, renderMode } = useContext(StylesContext); | |
let head = ( | |
<head> | |
<meta charSet="utf-8" /> | |
<meta name="viewport" content="width=device-width,initial-scale=1" /> | |
{title ? <title>{title}</title> : null} | |
<Meta /> | |
<Links /> | |
{styles} | |
</head> | |
); | |
let body = ( | |
<body> | |
{children} | |
<ScrollRestoration /> | |
<Scripts /> | |
{process.env.NODE_ENV === 'development' && <LiveReload />} | |
</body> | |
); | |
switch (renderMode) { | |
case 'head': | |
return head; | |
case 'body': | |
return body; | |
default: | |
return ( | |
<html lang="en"> | |
{head} | |
{body} | |
</html> | |
); | |
} | |
} | |
... |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { createContext } from 'react'; | |
import { ServerStyleSheet } from 'styled-components'; | |
export default createContext<{ | |
styles: React.ReactNode[]; | |
renderMode: 'head' | 'body' | 'all'; | |
}>({ styles: [], renderMode: 'all' }); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment