I am trying to render the whole page in React
only then sending it to the browser. I am getting the following error:
Invariant Violation: Invalid tag:
<!doctype html>
The line that is producing this error is ReactDOMServer.renderToString(el);
:
fs.readFile('./public/index.html',"utf8", function (err, data){
/*res.writeHead(200, {'Content-Type': 'text/html','Content-Length':data.length});
res.write(data);
res.end();*/
var el = React.createElement(data);
console.log("React element was successfully created!");
-----> var html = ReactDOMServer.renderToString(el);
res.send(html);
});
The html
file looks the following way:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
...
<title>React App</title>
</head>
<body>
<div id="root"></div>
<script type="text/javascript" src="bundle.js" charset="utf-8">
</script>
</body>
</html>
How to fix the error? Any suggestions would be greatly appreciated.
Update
I tried to do the following:
var mainData = prepareDataForScatterChart(result);
const html = ReactDOMServer.renderToString(`<App
mainData=${mainData}/>`);
fs.readFile('./public/index.html',"utf8", function (err, data){
const document = data.replace(/<div id="app"><\/div>/, `<div
id="app">${html}</div>`);
res.send(document);
The error is gone, but after I load the page there are errors that mean that the data was not passed to the App
.
Update
I got it working on the server by adding babel-node
, but browser still somehow is not getting the data. So, in the App
I am printing out the mainData
and it is there in the node
console, but in browser it is shown as undefined
. Here is the code that I am using now:
const html = ReactDOMServer.renderToString(<App mainData={mainData}/>);
I am trying to render the whole page in React
only then sending it to the browser. I am getting the following error:
Invariant Violation: Invalid tag:
<!doctype html>
The line that is producing this error is ReactDOMServer.renderToString(el);
:
fs.readFile('./public/index.html',"utf8", function (err, data){
/*res.writeHead(200, {'Content-Type': 'text/html','Content-Length':data.length});
res.write(data);
res.end();*/
var el = React.createElement(data);
console.log("React element was successfully created!");
-----> var html = ReactDOMServer.renderToString(el);
res.send(html);
});
The html
file looks the following way:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
...
<title>React App</title>
</head>
<body>
<div id="root"></div>
<script type="text/javascript" src="bundle.js" charset="utf-8">
</script>
</body>
</html>
How to fix the error? Any suggestions would be greatly appreciated.
Update
I tried to do the following:
var mainData = prepareDataForScatterChart(result);
const html = ReactDOMServer.renderToString(`<App
mainData=${mainData}/>`);
fs.readFile('./public/index.html',"utf8", function (err, data){
const document = data.replace(/<div id="app"><\/div>/, `<div
id="app">${html}</div>`);
res.send(document);
The error is gone, but after I load the page there are errors that mean that the data was not passed to the App
.
Update
I got it working on the server by adding babel-node
, but browser still somehow is not getting the data. So, in the App
I am printing out the mainData
and it is there in the node
console, but in browser it is shown as undefined
. Here is the code that I am using now:
const html = ReactDOMServer.renderToString(<App mainData={mainData}/>);
Share
Improve this question
edited Feb 7, 2018 at 1:02
Nikita Vlasenko
asked Feb 6, 2018 at 23:41
Nikita VlasenkoNikita Vlasenko
4,3528 gold badges54 silver badges96 bronze badges
6
-
You're trying to render that HTML page as JSX. That's why
<!doctype html>
is invalid (because that's invalid JSX). You need to import your bundle into the server and render the root ponent, usingReactDOMServer.renderToString(<App />)
. Here's an example – Sidney Commented Feb 6, 2018 at 23:49 - Here's an example github./pizza-r0b/isomorphic-redux-react-webpack-starter/… - the above states you need to pass a valid ponent to createElement – pizzarob Commented Feb 6, 2018 at 23:51
-
I am having now trouble with passing the parameters to the
App
element now. I do not knowRedux
... Could I just useReact
? – Nikita Vlasenko Commented Feb 7, 2018 at 0:25 -
@Sidney Actually with the
const html = ReactDOMServer.renderToString(<App/>);
I am getting an error, it can not parse it. – Nikita Vlasenko Commented Feb 7, 2018 at 0:28 - If you use JSX in your server code, it needs to be transpiled. The example I linked shows how to set that up through Webpack and Babel. – Sidney Commented Feb 7, 2018 at 0:38
2 Answers
Reset to default 2import React from 'react';
import { renderToString } from 'react-dom/server';
// import your app ponent containing the html structure.
import App from './App.jsx';
// Get your data as required.
const mainData = {};
res.send(
renderToString(`<!DOCTYPE html>${<App mainData={mainData}/>}`)
);
Using fs
to load a static html file and using replace()
are unnecessary unless you have pelling reasons to do so.
I'm using the streaming variant.
You can do this (working with express
and react-dom
, but should work with any stream):
function streamingRender(code, res, ponent) {
res.status(code)
res.write("<!DOCTYPE html>")
renderToNodeStream(ponent).pipe(res)
}