最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - React: server side rendering, Invariant Violation: Invalid tag: <!doctype html> - Stack Overflow

programmeradmin3浏览0评论

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, using ReactDOMServer.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 know Redux... Could I just use React? – 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
 |  Show 1 more ment

2 Answers 2

Reset to default 2
import 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)
}

与本文相关的文章

发布评论

评论列表(0)

  1. 暂无评论