React+Express+ChakraUI SSR中className不匹配问题求助
解决Chakra UI SSR渲染时客户端与服务端className不匹配问题
问题概述
基于React + Chakra UI + Express SSR的项目,引入Box组件后出现SSR渲染无样式的问题,控制台报错:
Prop
classNamedid not match. Server: "null" Client: "css-1xip3bv"
核心原因是服务端渲染时用原生div替代了Chakra的Box组件,导致服务端无法生成对应的emotion样式className,客户端hydrate时出现不匹配。
解决方案
1. 移除服务端/客户端组件分支逻辑
删除App.jsx中根据环境切换组件的代码,服务端必须渲染Box组件才能生成一致的className和样式:
修改后的App.jsx:
import React from 'react' import { Box } from '@chakra-ui/react' import NumberInput from './components/NumberInput' const App = () => { return ( <> <Box bg="red"> <h1>What is the HTTP code?</h1> </Box> <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
2. 确保服务端与客户端使用相同的emotion缓存实例
创建共享的emotion缓存文件createCache.js,服务端和客户端统一导入使用:
import { createCache } from '@emotion/cache' export const cache = createCache({ key: 'chakra-ui-ssr', prepend: true, // 保证服务端样式优先级高于客户端 })
服务端和客户端的CacheProvider都要传入这个缓存实例,避免各自生成不同的className。
3. 验证Babel配置正确性
当前Babel配置已正确开启emotion的SSR支持,保持现有配置即可:
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 } ]] })
4. 确认服务端样式提取逻辑正确
服务端通过extractCriticalToChunks和constructStyleTagsFromChunks提取的样式已正确插入到HTML头部,确保客户端hydrate时能读取到服务端生成的样式,避免重新生成className。
修改后效果
服务端渲染时会为Box组件生成对应的className和样式,客户端hydrate时className完全匹配,Box的红色背景样式正常显示。
内容的提问来源于stack exchange,提问作者NyxNight
相关产品推荐
相关产品推荐

