I'm working on setting up server-side rendering for my React/Express app, but I'm encountering a syntax error relating to the call to the react-dom/server renderToString() method. I'm loosely following this tutorial - http://crypt.codemancers.com/posts/2016-09-16-react-server-side-rendering/
index.js (Express app root):
'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))
})
})
However, this causes the error:
const appHtml = reactDomServer.renderToString(<RouterContext {...props}/>)
^
SyntaxError: Unexpected token <
All of the similar examples that I've seen have a straight JSX component dropped in... what am I missing?
I believe the issue stems from the fact that requiring babel-register will not work for the file you import it in, but for files that get imported afterwards. So the JSX syntax of <RouterContext will not be picked up by the renderToString method. This has happened to me before and including babel-register for the syntax never felt clean to me anyway.
What I personally have done and many others do is this: readDomServer.renderToString(React.createElement(RoutingContext, props)) using the createElement method in React, you can accomplish the same thing. This will solve your issue.
babel-register doesn't process the file it is called from, see https://stackoverflow.com/a/29425761/1795821
You'll need to put the app.get() called into another file, or use a different method of loading Babel.
So make a new renderReact.js file with
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))
})
})
}
Then back in your index.js do this instead
let renderReact = require('./renderReact.js');
renderReact(app);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With