-
Notifications
You must be signed in to change notification settings - Fork 247
Open
Description
Hello,
I'm using Remix with Emotion and have encountered a server-side rendering issue: when I wrap the app in <ThemeProvider>
from @emotion/react
and try to access the theme
inside a styled component (or using useTheme()
), the theme object is {}
during SSR. On the client side, everything works fine.
I'm basing my setup on this Remix + MUI example, with slight modifications:
https://github.com/mui/material-ui/blob/master/examples/material-ui-remix-ts/app/entry.server.tsx
Do you have a relevant example with a theme, or maybe you know where I made a mistake in the configuration?
Here is the relevant SSR configuration:
const handleBrowserRequest = (
request: Request,
responseStatusCode: number,
responseHeaders: Headers,
remixContext: EntryContext,
) => {
const cache = createEmotionCache();
const { extractCriticalToChunks } = createEmotionServer(cache);
function MuiRemixServer() {
return (
<ServerStyleContext.Provider value={null}>
<CacheProvider value={cache}>
<ThemeProvider theme={theme}>
<RemixServer context={remixContext} url={request.url} />
</ThemeProvider>
</CacheProvider>
</ServerStyleContext.Provider>
);
}
// Render the component to a string.
const html = ReactDOMServer.renderToString(<MuiRemixServer />);
// Grab the CSS from emotion
const chunks = extractCriticalToChunks(html);
const markup = ReactDOMServer.renderToString(
<ServerStyleContext.Provider value={chunks.styles}>
<CacheProvider value={cache}>
<ThemeProvider theme={theme}>
<CssBaseline />
<RemixServer context={remixContext} url={request.url} />
</ThemeProvider>
</CacheProvider>
</ServerStyleContext.Provider>,
);
responseHeaders.set("Content-Type", "text/html");
// Enhanced cache control headers to prevent aggressive browser caching
responseHeaders.set("Cache-Control", "no-store, no-cache, must-revalidate, proxy-revalidate");
responseHeaders.set("Surrogate-Control", "no-store");
responseHeaders.set("Pragma", "no-cache");
responseHeaders.set("Expires", "0");
// Add a unique timestamp to force browsers to refetch resources
responseHeaders.set("X-Content-Timestamp", new Date().getTime().toString());
return new Response(`<!DOCTYPE html>${markup}`, {
status: responseStatusCode,
headers: responseHeaders,
});
};
A simplified styled component that reproduces the issue:
import styled from "@emotion/styled";
export const StyledDiv = styled.div`
${({ theme }) => {
console.log("Theme on server:", theme); // Outputs {}
return "";
}}
`;
Environment information:
react
version: 18.2.0@emotion/react
version: 11.13.3@emotion/server
version: 11.11.0@mui/material
version: 6.1.6@remix-run/dev
version: 2.16.4
Metadata
Metadata
Assignees
Labels
No labels