React SSR 中调用 ReactDOM.hydrate() 的正确位置是什么?
React SSR hydrate 调用位置问题解答
ReactDOM.hydrate() 是客户端侧专属API,绝对不能在服务端应用中调用,必须在用户浏览器加载的前端JS包中执行。
核心逻辑说明
SSR 分为两个独立的渲染阶段,分工完全不同:
- 运行在3003端口的服务端只负责调用
ReactDOMServer.renderToString()(或renderToPipeableStream等服务端专属API)生成React组件对应的静态HTML字符串,将该字符串插入到返回的HTML模板对应节点中即可,不需要处理任何和hydrate相关的逻辑。 - 你当前遇到的事件处理器失效、React DevTools无法识别应用的问题,本质是浏览器只拿到了静态HTML内容,没有执行客户端hydrate逻辑把静态DOM和React虚拟DOM做关联、绑定交互事件导致的。
正确操作步骤
- 首先确保3003端口的服务返回的HTML模板中,body末尾已经引入了你的前端项目打包生成的JS bundle文件,示例:
<script src="/你的前端包路径/bundle.js"></script>,这个JS包会被浏览器下载并执行。 - 修改你原有CSR项目的入口文件:把原本的
ReactDOM.render(<App />, 根DOM节点)代码,替换为hydrate逻辑:- React 17及更早版本:
ReactDOM.hydrate(<App />, 根DOM节点) - React 18及以上版本:
注意这里用到的import { hydrateRoot } from 'react-dom/client'; hydrateRoot(根DOM节点, <App />);App组件,必须和服务端渲染时使用的组件完全一致,组件结构、初始props都不能有差异,否则会出现hydrate不匹配报错。 - React 17及更早版本:
- 重新打包前端项目,确保服务端HTML模板中引入的是修改后的新版JS包即可。
常见注意事项
- 不要在组件初始渲染逻辑中做服务端、客户端差异化的条件判断(比如直接判断
window是否存在来渲染不同内容),这类逻辑需要放到useEffect回调中执行,否则会触发hydrate不匹配问题,导致事件绑定失效。 - 服务端返回的HTML中,根节点的结构要和客户端渲染的根节点结构完全一致,不要额外加多余的空格、注释等内容。
内容的提问来源于stack exchange,提问作者PranavPinarayi
相关产品推荐
相关产品推荐

