
本文旨在解决React服务端渲染(SSR)中常见的“Expected server HTML to contain a matching in
理解React SSR水合(Hydration)机制
在react服务端渲染(ssr)应用中,服务器会预先生成html字符串并发送给客户端。客户端的react应用接收到这份html后,并不会从头开始构建dom,而是尝试“水合”已有的dom结构。水合过程是react将客户端javascript逻辑(如事件监听器、状态管理)附加到服务器预渲染的html上的过程。为了实现高效的水合,react要求服务器生成的html结构与客户端首次渲染时预期的dom结构完全一致。任何细微的差异,包括额外的文本节点(如换行符、空格),都可能导致水合失败,从而触发类似“expected server html to contain a matching
常见问题:EJS模板中的隐形空白
当使用Express和EJS等模板引擎进行React SSR时,一个常见且容易被忽视的问题是EJS模板中注入React组件的方式。考虑以下EJS模板片段:
在这个例子中,reactComponent变量包含了由renderToString生成的React组件的HTML字符串。表面上看,它被正确地放置在
... ...
React的水合算法在检查
解决方案:确保组件的直接注入
解决这个问题的关键在于消除EJS模板中reactComponent注入点周围的所有非预期空白。这意味着将reactComponent直接放置在根DOM元素的开始标签和结束标签之间,且不引入任何换行符或空格。
修改后的EJS模板示例:
通过这种方式,服务器生成的HTML将是:
... ...
现在,
示例代码与实践
以下是一个完整的Express、EJS和React SSR设置示例,展示了如何正确处理组件注入:
1. React组件 (SchoolPage.jsx)
import React from 'react';import MiniSearchBar from './MiniSearchBar'; // 假设有这个组件import ContentContainer from './ContentContainer'; // 假设有这个组件export default function SchoolPage() { return ( @@##@@ > );}</pre>2. Express服务器 (server.js)
import express from 'express';import path from 'path';import ejs from 'ejs';import React from 'react';import { renderToString } from 'react-dom/server';import SchoolPage from './dist/SchoolPage.js'; // 假设打包后的组件const app = express();const PORT = process.env.PORT || 3000;app.use(express.static(path.join(__dirname, 'public'))); // 静态文件服务app.get("/campus/:id/locations", async (req, res) => { const reactComponentHtml = renderToString(); const filePath = path.join(__dirname, "dist", "school-page.ejs"); // EJS模板路径 ejs.renderFile(filePath, { reactComponent: reactComponentHtml }, (err, html) => { if (err) { console.error("Error rendering template:", err); return res.status(500).send("Internal Server Error"); } res.send(html); });});app.listen(PORT, () => { console.log(`Server listening on port ${PORT}`);});
3. EJS模板 (school-page.ejs)
Campus Eats <!-- 关键改动:确保 无空白地直接嵌入 -->
注意事项:
id="root" vs class="root": 尽管将class="root"改为id="root"对解决此特定的水合警告并非决定性因素,但将React应用的根元素使用id="root"是普遍的最佳实践,因为它提供了唯一的标识符,方便客户端JavaScript精确地挂载React应用。
客户端水合: 确保客户端的JavaScript文件(例如school-page.js)在加载后会使用ReactDOM.hydrateRoot(或旧版ReactDOM.hydrate)来挂载React应用到id="root"元素上,例如:
import React from 'react';import { hydrateRoot } from 'react-dom/client';import SchoolPage from './SchoolPage'; // 客户端打包后的组件const container = document.getElementById('root');hydrateRoot(container, );
其他水合不匹配: 除了EJS模板中的空白,其他因素也可能导致水合不匹配,例如:
客户端在水合前对DOM进行了修改。服务器和客户端在渲染逻辑上存在差异(例如,基于浏览器API的代码在服务器上无法执行,导致DOM结构不同)。使用dangerouslySetInnerHTML时内容不匹配。React组件内部条件渲染逻辑在服务器和客户端执行结果不同。
总结
React SSR中的水合警告“Expected server HTML to contain a matching in

以上就是解决React SSR水合警告:EJS模板中意外空白引发的DOM不匹配的详细内容,更多请关注创想鸟其它相关文章!
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/1528309.html
微信扫一扫
支付宝扫一扫