React/Express - 在调用renderToString()时出现“Unexpected token <”

11

我正在为我的React/Express应用程序设置服务器端渲染,但在调用react-dom/serverrenderToString()方法时遇到语法错误。我松散地按照这个教程 - http://crypt.codemancers.com/posts/2016-09-16-react-server-side-rendering/ 进行操作。

index.js(Express应用程序根目录):

'use strict'
require('babel-register')({
    presets: ['es2015', 'react']
});

const express = require('express')
const path = require('path')
const app = express()
const React = require('react')
const reactDomServer = require('react-dom/server')
const routes = require('./src/routes.jsx')
const reactRouter = require('react-router')
let { match, RouterContext } = reactRouter

app.get('*', (req, res) => {
    match({ routes: routes, location: req.url }, (err, redirect, props) => {
        const appHtml = reactDomServer.renderToString(<RouterContext {...props}/>)
        res.send(renderPage(appHtml))
    })
})

然而,这会引起错误:

const appHtml = reactDomServer.renderToString(<RouterContext {...props}/>)
                                              ^
SyntaxError: Unexpected token <

我看到的所有类似示例都是直接将JSX组件放入... 我错过了什么吗?

2个回答

8

babel-register不会处理它所在的文件,请参见https://dev59.com/aF4b5IYBdhLWcg3wZwu3#29425761

你需要将被调用的app.get()放入另一个文件中,或者使用另一种加载Babel的方法。

因此,可以创建一个名为renderReact.js的新文件,并添加以下内容:

module.exports = function(app) {
  app.get('*', (req, res) => {
    match({ routes: routes, location: req.url }, (err, redirect, props) => {
        const appHtml = reactDomServer.renderToString(<RouterContext {...props}/>)
        res.send(renderPage(appHtml))
    })
  })
}

然后在你的index.js中,改为这样做。
let renderReact = require('./renderReact.js');
renderReact(app);

6
我认为问题源于需要 babel-register 的文件不会对导入它的文件起作用,而是对后来导入的文件起作用。因此,<RouterContext 的 JSX 语法不会被 renderToString 方法捕获。我之前也遇到过这个问题,而且使用 babel-register 处理语法从来没有让我感觉很干净。

我个人和许多其他人做的是:使用 React 中的 createElement 方法,readDomServer.renderToString(React.createElement(RoutingContext, props)) 可以实现同样的效果。这将解决你的问题。


太好了,谢谢!我选择了另一个答案,因为它特别涉及到babel-register的正确行为,但是这个答案也很好,我可能会在我的实际应用中使用它。 - skwidbreth
没问题 @skwidbreth,很高兴你找到了解决方案。 - Dwayne Charrington
有没有一种方法可以实现这个方法,使其适用于<StaticRouter>元素及其参数,并且<App />在其中? - sheptang

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接