Skip to content

Instantly share code, notes, and snippets.

@ryanflorence
Last active August 4, 2022 06:46
Show Gist options
  • Save ryanflorence/b7f1653404b350483909609e435a8a2d to your computer and use it in GitHub Desktop.
Save ryanflorence/b7f1653404b350483909609e435a8a2d to your computer and use it in GitHub Desktop.
Remix + Styled Components
import ReactDOMServer from "react-dom/server";
import type { EntryContext } from "@remix-run/core";
import Remix from "@remix-run/react/server";
import { renderToString } from "react-dom/server";
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();
// first pass to collect styles
renderToString(
sheet.collectStyles(
<StylesContext.Provider value={null}>
<Remix context={remixContext} url={request.url} />
</StylesContext.Provider>
)
);
// get the styles
let styles = sheet.getStyleTags();
sheet.seal();
// second time with the styles on context
let markup = ReactDOMServer.renderToString(
<StylesContext.Provider value={styles}>
<Remix context={remixContext} url={request.url} />
</StylesContext.Provider>
);
return new Response("<!DOCTYPE html>" + markup, {
status: responseStatusCode,
headers: {
...Object.fromEntries(responseHeaders),
"Content-Type": "text/html"
}
});
}
import { Meta, Scripts } from "@remix-run/react";
import { useContext } from "react";
import StylesContext from "./stylesContext";
export default function Root() {
// get styles from context
let styles = useContext(StylesContext);
return (
<html>
<head>
<Meta />
{styles}
</head>
<body>
<Scripts />
</body>
</html>
);
}
import { createContext } from "react";
export default createContext<null | string>(null);
@martinmckenna
Copy link

martinmckenna commented Aug 4, 2022

why not just inject the style tags at the end of the <head /> like so?

    const markupWithStyles = markup.replace(
      /<\s*\/\s*head\s*>/gm,
      `${styleTags}</head>`
    );

    return new Response("<!DOCTYPE html>" + markupWithStyles, {
      status: responseStatusCode,
      headers: responseHeaders,
    });

edit: nvm this solution still causes the loss of styles upon rehydration

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment