不变性违反:_registerComponent(…):目标容器不是DOM元素

我在一个不起眼的React示例页面后得到这个错误:

不变性违反:_registerComponent(…):目标容器不是一个DOM元素。

这是我的代码:

/** @jsx React.DOM */
'use strict';


var React = require('react');


var App = React.createClass({
render() {
return <h1>Yo</h1>;
}
});


React.renderComponent(<App />, document.body);

HTML:

<html>
<head>
<script src="/bundle.js"></script>
</head>
<body>
</body>
</html>

这是什么意思?

251386 次浏览

到脚本执行时,document元素还不可用,因为script本身在head. xml文件中。虽然将script保存在headDOMContentLoaded事件上渲染中是一个有效的解决方案,但script0更好

<html>
<head>
</head>
<body>
<div id="root"></div>
<script src="/bundle.js"></script>
</body>
</html>

bundle.js中,调用:

React.render(<App />, document.getElementById('root'));

你应该总是呈现一个嵌套的__ABC0而不是body否则,各种各样的第三方代码(谷歌字体加载器,浏览器插件,等等)可以在React不期望它时修改body DOM节点,并导致非常难以跟踪和调试的奇怪错误。阅读更多关于这个问题的信息。

script放在底部的好处是,如果你将React服务器渲染添加到项目中,它不会阻塞渲染,直到脚本加载。


更新:(2015年10月07日| v0.14)

React.render已弃用,请使用ReactDOM.render 相反。< / p >

例子:

import ReactDOM from 'react-dom';


ReactDOM.render(<App />, document.getElementById('root'));

准备好功能可以这样使用:

$(document).ready(function () {
React.render(<App />, document.body);
});

如果你不想使用jQuery,你可以使用onload函数:

<body onload="initReact()">...</body>

/index.html

<!doctype html>
<html>
<head>
<title>My Application</title>
<!-- load application bundle asynchronously -->
<script async src="/app.js"></script>
<style type="text/css">
/* pre-rendered critical path CSS (see isomorphic-style-loader) */
</style>
</head>
<body>
<div id="app">
<!-- pre-rendered markup of your JavaScript app (see isomorphic apps) -->
</div>
</body>
</html>

/app.js

import React from 'react';
import ReactDOM from 'react-dom';
import App from './components/App';


function run() {
ReactDOM.render(<App />, document.getElementById('app'));
}


const loadedStates = ['complete', 'loaded', 'interactive'];


if (loadedStates.includes(document.readyState) && document.body) {
run();
} else {
window.addEventListener('DOMContentLoaded', run, false);
}

IE9 (+)

请注意:头文件中有<script async src="..."></script>确保浏览器将开始下载JavaScript包之前 HTML内容被加载。

来源:React入门套件isomorphic-style-loader

在我的例子中,这个错误是由引入新类时热重新加载引起的。在项目的这个阶段,使用普通的监视器来编译代码。

对于那些使用ReactJS的人。Net并在发布后得到这个错误:

检查你的.jsx文件的属性,确保Build Action被设置为Content。那些设置为None的将不会被发布。我从这个SO答案中找到了这个解决方案。

我遇到类似/相同的错误信息。在我的例子中,我没有定义用于呈现ReactJS组件的目标DOM节点。确保HTML目标节点有适当的“id”或“name”,以及其他HTML属性(适合您的设计需要)。

只是一个大胆的猜测,如何向index.html添加以下内容:

type="javascript"

是这样的:

<script type="javascript" src="public/bundle.js"> </script>

对我来说很管用!: -)

是的,基本上你所做的是正确的,除了你忘记JavaScript在很多情况下是同步的,所以你在DOM加载之前运行代码,有几个方法来解决这个问题:

1)检查DOM是否完全加载,然后做任何你想做的事情,例如,你可以听DOMContentLoaded:

<script>
document.addEventListener("DOMContentLoaded", function(event) {
console.log("DOM fully loaded and parsed");
});
</script>

2)非常常见的方法是将script标签添加到document的底部(在body标签之后):

<html>
<head>
</head>
<body>
</body>
<script src="/bundle.js"></script>
</html>

3)使用window.onload,当整个页面加载时触发(img等)

window.addEventListener("load", function() {
console.log("Everything is loaded");
});

4)使用document.onload,当DOM准备好时触发:

document.addEventListener("load", function() {
console.log("DOM is ready");
});

还有更多的选项来检查DOM是否准备好了,但简单的答案是在确保你的DOM准备好了在每种情况下之前运行任何脚本…

JavaScript与DOM元素一起工作,如果它们不可用,将返回,可能会破坏整个应用程序…所以总是确保你完全准备好运行你的JavaScript之前…

我也犯了同样的错误。它原来是由一个简单的打字错误造成的更改我的代码从:

document.getElementById('root')

document.querySelector('root')
注意缺少了“#” 它应该是

document.querySelector('#root')

只是发布,以防它帮助其他人解决这个错误。

如果你使用webpack来渲染你的react,并在你的react中使用HtmlWebpackPlugin,这个插件会自己构建空白的index.html并在其中注入js文件,所以它不包含div元素,就像HtmlWebpackPlugin文档一样,你可以构建自己的index.html并将其地址给这个插件。 在我的webpack.config.js

plugins: [
new HtmlWebpackPlugin({
title: 'dev',
template: 'dist/index.html'
})
],

这是index。html文件

<!DOCTYPE html>
<html lang="en">
<head>
<link rel="shortcut icon" href="">
<meta name="viewport" content="width=device-width">
<title>Epos report</title>
</head>
<body>
<div id="app"></div>
<script src="./bundle.js"></script>
</body>
</html>

这很简单,只是基本的HTML CSS js和从js渲染脚本

mport React from 'react';
import ReactDOM from 'react-dom';
import './index.css';


var destination = document.querySelector('#container');


ReactDOM.render(
<div>
<p> hello world</p>
</div>, destination




); 
body{


text-align: center;
background-color: aqua;
padding: 50px;
border-color: aqua;
font-family: sans-serif;
}
#container{
display: flex;
justify-content: flex;


}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
   

<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#000000" />
<meta
name="description"
content="Web site created using create-react-app"
/>
<title> app  </title>
</head>
<body>
 



<div id="container">
      

</div>


</body>
</html>

当你有:

错误:目标容器不是DOM元素。

你可以使用DOMContentLoaded事件或移动你的<script ...></script>标签在你的主体底部。

DOMContentLoaded事件在初始HTML文档完全加载和解析时触发,而不需要等待样式表、图像和子帧完成加载。

document.addEventListener("DOMContentLoaded", function(event) {
ReactDOM.render(<App />, document.getElementById('root'));
})

在我使用jQuery的情况下-出于某种原因,window.onload不像jQuery的onload一样

所以这个对我很有用:

<script>
$(function () {          <= replacing window.onload = function() {
// Begin Swagger UI call region
const ui = SwaggerUIBundle({
...


window.ui = ui;
});
</script>

在我的例子中,html文件中的所有内容都被正确设置(即脚本位于body标签的底部)。通过将组件的定义移动到一个单独的文件,从组件呈现给ReactDOM的地方解决了这个问题。

所以最初我有

import React from 'react';
import ReactDOM from 'react-dom';


class Comp extends React.Component {
// component definition
}


ReactDOM.render(
<Comp />,
document.getElementById('root')
);

在我将组件定义移动到一个单独的文件并导入后,问题得到了解决

import React from 'react';
import ReactDOM from 'react-dom';


import Comp from './CompFile';


ReactDOM.render(
<Comp />,
document.getElementById('root')
);

对于我的情况,我确实在index.js中犯了以下错误,并进行了更正。

错误:

import React from "react";
import ReactDOM from "react-dom";
import App from "./App";


ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>
);

解决方案: document.getElementById("root")

import React from "react";
import ReactDOM from "react-dom";
import App from "./App";


ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
document.getElementById("root") // declared
);

webpack。我们可以选择使用htmlPlugin加载html文件,而不需要定义它。在这种情况下,Webpack 将创建一个html文件,其中的script标记位于以上的root-div元素之上。一个快速的解决方法是动态地添加一个新的div到dom中,然后将react dom写入其中。这可以在你的reactDom渲染函数上完成(通常)定义在index.js文件中,如下所示。

import React from "react";
import ReactDOM from "react-dom";
import App from "./components/App";
import { BrowserRouter as Router } from "react-router-dom";
ReactDOM.render(
<Router>
<App />
</Router>,
document.body.appendChild(document.createElement("div"))
);