简体   繁体   中英

React: server side rendering, Invariant Violation: Invalid tag: <!doctype html>

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}/>);
import React from 'react';
import { renderToString } from 'react-dom/server';
// import your app component 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 compelling 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, component) {
  res.status(code)
  res.write("<!DOCTYPE html>")
  renderToNodeStream(component).pipe(res)
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM