使用renderToStaticMarkup渲染Material-UI组件时样式不生效问题
Material-UI组件用renderToStaticMarkup渲染后样式失效的解决办法
在尝试将Material-UI组件集成到其他库时,使用renderToStaticMarkup渲染组件后,发现通过styled创建的自定义样式完全没有生效。相关代码如下:
import * as React from "react"; import ReactDOM from "react-dom/client"; import Button from "@mui/material/Button"; import { styled } from "@mui/material"; import { renderToStaticMarkup } from "react-dom/server"; const StyledButton = styled(Button)(() => ({ backgroundColor: "red" })); ReactDOM.createRoot(document.querySelector("#root")).render( <React.StrictMode> <div dangerouslySetInnerHTML={{ __html: renderToStaticMarkup(<StyledButton>Test</StyledButton>) }} /> </React.StrictMode> );
问题原因
renderToStaticMarkup是React的服务端渲染方法,它只会生成静态HTML结构,不会触发Material-UI客户端的样式注入逻辑。而styled生成的组件样式,依赖Material-UI的客户端样式引擎动态将CSS注入到页面中,因此直接用该方法渲染出的HTML没有对应的样式。
解决方案
方案一:客户端直接渲染组件(优先推荐)
如果你的场景是纯客户端集成,完全没必要使用renderToStaticMarkup,直接渲染组件即可,Material-UI会自动处理样式注入:
import * as React from "react"; import ReactDOM from "react-dom/client"; import Button from "@mui/material/Button"; import { styled } from "@mui/material"; const StyledButton = styled(Button)(() => ({ backgroundColor: "red" })); ReactDOM.createRoot(document.querySelector("#root")).render( <React.StrictMode> <StyledButton>Test</StyledButton> </React.StrictMode> );
方案二:手动收集并注入样式(需用renderToStaticMarkup时)
如果确实需要生成静态HTML字符串供其他库使用,可以通过Material-UI的样式管理器手动收集样式,再注入到页面:
import * as React from "react"; import ReactDOM from "react-dom/client"; import Button from "@mui/material/Button"; import { styled, createStyleSheetManager } from "@mui/material"; import { renderToStaticMarkup } from "react-dom/server"; const StyledButton = styled(Button)(() => ({ backgroundColor: "red" })); // 创建样式集合用于收集组件样式 const styleSheets = new Set(); const styleManager = createStyleSheetManager({ sheet: styleSheets }); // 渲染组件并同步收集样式 const staticHtml = renderToStaticMarkup( <styleManager> <StyledButton>Test</StyledButton> </styleManager> ); // 将收集到的样式转换为可注入的CSS字符串 const collectedCss = Array.from(styleSheets).map(sheet => sheet.css).join(''); // 渲染时同时注入样式和静态HTML ReactDOM.createRoot(document.querySelector("#root")).render( <React.StrictMode> <style>{collectedCss}</style> <div dangerouslySetInnerHTML={{ __html: staticHtml }} /> </React.StrictMode> );
这种方式通过createStyleSheetManager捕获styled组件生成的样式,再通过<style>标签手动注入到页面,就能让静态HTML的样式正常生效。
内容的提问来源于stack exchange,提问作者TheAschr
相关产品推荐
相关产品推荐

