I have a simple project where I am exposing the built FE project (which has React and ChakraUI) through an express server. Things go well until I import a Box component from chakra. It gets rendered through SSR, but without any styling. From what I understand, the classNames from the client are not in sync with the ones on the server. Is there any way I can fix this?
Error message: Prop className did not match. Server: "null" Client: "css-1xip3bv".
SSR part on the server:
// ssr
const renderFullPage = (html, styles) => {
return `<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>What is the HTTP code?</title>
${styles}
<script defer src="./bundle.js"></script>
</head>
<body>
<div id="app">${html}</div>
</body>
</html>`;
}
app.use('^/$', (req, res) => {
const html = renderToString(
<CacheProvider value={cache}>
<ChakraBaseProvider theme={theme}>
<CSSReset />
<App />
</ChakraBaseProvider>
</CacheProvider>,
)
const emotionChunks = extractCriticalToChunks(html)
const emotionCss = constructStyleTagsFromChunks(emotionChunks)
res.contentType('text/html')
res.status(200)
res.send(renderFullPage(html, emotionCss))
})
index.js on the FE side and the App component:
index.js
import * as React from 'react'
import { hydrateRoot, createRoot } from 'react-dom/client'
import { ChakraBaseProvider, CSSReset, extendBaseTheme } from '@chakra-ui/react'
import { CacheProvider } from '@emotion/react'
import App from './App'
import { cache } from './createCache'
const theme = extendBaseTheme({
colors: {
red: '#C53030',
}
})
const container = document.getElementById('app')
hydrateRoot(
container,
<CacheProvider value={cache}>
<ChakraBaseProvider theme={theme}>
<CSSReset />
<App />
</ChakraBaseProvider>
</CacheProvider>,
)
App.jsx
import React from 'react'
import { Box } from '@chakra-ui/react'
import NumberInput from './components/NumberInput'
const App = () => {
const isClient = typeof window !== "undefined";
const Component = isClient ? Box : 'div'
return (
<>
<Component bg="red">
<h1>What is the HTTP code?</h1>
</Component>
<div>"What is the HTTP code?" is a project designed to make people's life easier when dealing
with HTTP response status codes. The purpose is to create a lightweight, reliable and easy
to use tool that's accesible to everyone, whether you're a seasoned software developer or a
beginner just starting out. The HTTP response status codes are described in the internet
standard RFC 9110.
</div>
<NumberInput />
</>
)
}
export default App
I tried changing the babel file in a few ways, although I am not sure I'm doing it well, my current babel settings are these:
require('@babel/register')({
ignore: [/(node_modules)/],
presets: [
'@babel/preset-env',
'@babel/preset-react',
],
plugins: [[
"@emotion",
{
"sourceMap": true,
"autoLabel": "dev-only",
"labelFormat": "[local]",
"cssPropOptimization": true,
"ssr": true
}
]]
})
I am expecting the styling on the server to be in sync with the one on the client. For example if I add a red background to the Box component, it should be red, not white as it shows up right now.
Any help is very much appreciated, Thank you.