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


387

在制作平凡的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>

这是什么意思?


8
@ go-oleg:这是ES6的缩写。这不是问题,因为react-tools具有ES6编译器。看到这里
Dan Abramov 2014年

14
我遇到了同样的错误,并且正如其他人所建议的那样,这是因为您的bundle.js文件加载时间过早。将您的<script>标记移至正文(作为结束</ body>标记之前的最后一行)以解决此错误。
Todd R

2
多数民众赞成在这里没有帮助
daslicht

@daslicht我希望您找到了答案,但正好这样说:仔细检查您是否没有混淆类和ID。document.getElementById(“ foo”)永远不会找到读取<div class =“ foo”>的标签
Dave Kanter

Answers:


625

在执行脚本时,documentelement尚不可用,因为script其本身位于中head。虽然这是一个有效的解决方案,以保持scripthead渲染上DOMContentLoaded情况下,它甚至不如把你script在最底层的body 渲染根组件到div之前它是这样的:

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

并在 bundle.js致电:

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

您应始终渲染为div而不是嵌套body否则,body当React不期望时,各种第三方代码(Google字体加载器,浏览器插件等)都可以修改DOM节点,并导致难以跟踪和调试的奇怪错误。阅读有关此问题的更多信息。

关于放置的好处 script底部的好处是,如果您将React Server渲染添加到项目中,则在脚本加载之前它不会阻止渲染。


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

React.render 不推荐使用 ReactDOM.render 改用。

例:

import ReactDOM from 'react-dom';

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

3
我在webpack中使用import语句,仍然出现此错误。我以为webpack会照顾加载脚本的顺序,不是吗?
thetrystero's

4
考虑使用defer <script defer src =“ fb.me/react-0.14.7.js" ></script> <script defer src =” fb.me/react-dom-0.14.7.js"></脚本 > <!-立即输入您的应用代码-> <脚本延迟src =“ app.js”> </ script> </ body>
登陆

4
@thetrystero不,webpack不了解您的应用程序包与其所操作的DOM节点之间的相对位置。
Dan Abramov

1
这种神秘的错误-只需将脚本
放到

1
@DanAbramov不是这种情况,但是我通过使用没有完整关闭标签的目标容器收到了相同的错误(例如<section id =“” />)
Chris

53

/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入门套件同构样式加载器


5
这是ReactDOM.render不是React.render
康拉多·丰塞卡

警告说明:如果将您的反应设置为异步加载,则会创建竞争条件-如果浏览器在执行JS之前完成了页面解析,就可以了。如果在解析页面之前加载了JS,您最终将遇到与问题相同的问题。defer可能是一个更好的选择
BRasmussen

16

准备功能,可以使用这样的:

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

如果您不想使用jQuery,则可以使用以下onload函数:

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

6
我认为DOMContentLoaded甚至比loadjQuery使用的是)更合适。您也可以在JS中使用来执行此操作window.addEventListener,无需内联处理程序和全局函数。
Dan Abramov 2014年

3
注意,renderComponent将被淘汰。使用React.render()代替。
Tommyixi

2
我正在使用react-rails,因此无法将script标签移动到body标签底部。 $(document).ready解决了问题。哦,是的,用render代替renderComponent
ltrainpr

1
在React上使用jQuery是非常糟糕的做法。使用任何一个,但不能同时使用。
aggregate116​​6877

11

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

type="javascript"

像这样:

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

对我来说,它奏效了!:-)


3
仅供参考,这给我带来了问题,如何type="text/javascript"正常工作。
steezeburger '17

确实解决了我的问题,这很糟糕。有点伤心,但不确定是谁责怪这个人,做出反应或通天塔?
威廉·霍利,

6

我遇到了同样的错误。原来是将我的代码从以下位置更改后,由一个简单的错字引起的:

document.getElementById('root')

document.querySelector('root')

注意缺少的“#”应该是

document.querySelector('#root')

只是发布以防其他人解决此错误。


4

是的,基本上您所做的是正确的,只是您在很多情况下都忘记了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元素一起使用,如果它们不可用,则将返回null,可能会破坏整个应用程序...因此,请务必确保已准备就绪,然后再运行JavaScript ...


2

如果您使用webpack来呈现您的反应并在您的react中使用HtmlWebpackPlugin,则此插件将自行构建其空白index.html并在其中注入js文件,因此它不包含div元素,作为HtmlWebpackPlugin文档,您可以构建自己的索引。 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>

1
HtmlWebpackPlugin如果用来引用静态HTML文件,为什么还要在这里使用插件?
哈里·乔

1

在我的情况下,此错误是由于在引入新类时热重载引起的。在项目的那个阶段,请使用普通的观察者来编译您的代码。


1

对于使用ReactJS.Net并在发布后出现此错误的用户:

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


1

我遇到类似/相同的错误消息。就我而言,我没有用于定义ReactJS组件的目标DOM节点。确保使用适当的“ id”或“ name”以及其他HTML属性(适合您的设计需求)很好地定义了HTML目标节点。


我有类似的问题。在视图中,我有<code> if </ code>语句,如果满足条件,则应在其中生成预期的目标元素。在我的情况下,由于条件而没有渲染适当的元素,而是执行了脚本并试图将组件安装在DOM中不存在的元素上。
拉法尔·西普切

0

制作基本的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>


0

当你得到:

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

您可以使用DOMContentLoaded事件,也可以将<script ...></script>标签移动到正文的底部。

DOMContentLoaded事件触发时,最初的HTML文档已被完全加载和分析,而无需等待样式表,图片和完成加载子。

document.addEventListener("DOMContentLoaded", function(event) {
  ReactDOM.render(<App />, document.getElementById('root'));
})
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.