React无报错但JSDOM渲染的内容未在staff-home.html中正常显示
React渲染内容未注入到staff-home.html的问题解决
问题根因
- 你用JSDOM修改的只是服务端内存中临时加载的HTML文件的DOM副本,并未将修改后的内容返回给访问页面的用户
- 你配置了
app.use('/', express.static('pages'))静态资源规则,用户访问staff-home.html时,Express会直接返回原始未修改的pages/staff-home.html文件,和你修改的内存DOM无关联 - 当前你使用的
ReactDOM.render是客户端渲染API,不适合直接在服务端操作DOM场景使用
修复步骤
1. 替换服务端渲染API、新增自定义路由处理页面请求
修改routes/index.js代码如下:
const jsdom = require("jsdom"); const { JSDOM } = jsdom; // 引入服务端渲染专用API const ReactDOMServer = require('react-dom/server'); var express = require('express'); var router = express.Router(); var React = require('react'); var reactElement = React.createElement('h1', { className: 'header' }, 'This is React'); // 新增staff-home.html专属路由,优先处理页面请求 router.get('/staff-home.html', async (req, res) => { // 每次请求时读取文件、修改DOM、返回修改后的内容 const dom = await JSDOM.fromFile('/usr/src/app/pages/staff-home.html'); const root = dom.window.document.getElementById('root'); // 将React元素渲染为HTML字符串插入root节点 root.innerHTML = ReactDOMServer.renderToString(reactElement); // 序列化DOM为HTML字符串返回给客户端 res.send(dom.serialize()); }); /* GET home page. */ router.get('/', function(req, res, next) { res.render('index', { title: 'Express' }); }); module.exports = router;
2. 调整Express中间件顺序
修改app.js中的中间件加载顺序,将自定义路由放在静态资源中间件之前,确保自定义路由优先级更高:
// 先加载自定义路由 app.use('/', indexRouter); app.use('/users', usersRouter); app.use('/staffs', staffsRouter); app.use('/login', loginRouter); // 最后加载静态资源中间件 app.use('/', express.static('pages'));
可选优化方案
如果你不需要做服务端渲染,可以直接放弃服务端JSDOM的方案,把React渲染逻辑写到客户端JS文件中:
- 将React、ReactDOM的CDN引入添加到
staff-home.html的head标签中 - 把渲染逻辑写在
public/javascripts下的独立JS文件中,在staff-home.html末尾引入即可,无需服务端额外处理
内容的提问来源于stack exchange,提问作者Trang Le Phuong Nguyen
相关产品推荐
相关产品推荐

