Infracción invariable: _registerComponent (...): el contenedor de destino no es un elemento DOM


388

Me sale este error después de hacer una página de ejemplo de Reacción trivial:

Error no detectado: Infracción invariable: _registerComponent (...): el contenedor de destino no es un elemento DOM.

Aquí está mi código:

/** @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>

¿Qué significa esto?


8
@ go-oleg: Esta es la notación corta ES6. No es el problema porque react-tools tiene el transpilador ES6. Ver aquí
Dan Abramov

14
Me encontré con este mismo error, y como otros han sugerido, es porque su archivo bundle.js se está cargando demasiado pronto. Mueva su etiqueta <script> al cuerpo (como la última línea antes de la etiqueta de cierre </body>) para resolver este error.
Todd R

2
eso no ayuda aquí
daslicht

@daslicht Espero que hayas encontrado tu respuesta, pero así se dice: DOBLE COMPROBACIÓN de que no estás mezclando clases e identificaciones. document.getElementById ("foo") nunca, nunca, va a encontrar una etiqueta que lea <div class = "foo">
Dave Kanter

Respuestas:


626

En el momento en que se ejecuta el script, el documentelemento aún no está disponible, porque scriptsí mismo está en el head. Si bien es una solución válida para mantener scripten heady hacer que el DOMContentLoadedevento , que es aún mejor para poner su scripten la parte inferior de la body y hacer que los componentes de la raíz a una divantes de la siguiente manera:

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

y en el bundle.js, llame:

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

Siempre debe renderizar a un anidado en divlugar de body. De lo contrario, todo tipo de código de terceros (Google Font Loader, complementos del navegador, lo que sea) puede modificar el bodynodo DOM cuando React no lo espera y causar errores extraños que son muy difíciles de rastrear y depurar. Lea más sobre este tema.

Lo bueno de poner scripten la parte inferior es que no bloqueará la representación hasta que se cargue el script en caso de que agregue la representación del servidor React a su proyecto.


Actualización: (07 de octubre de 2015 | v0.14 )

React.renderestá en desuso, úselo en su ReactDOM.render lugar.

Ejemplo:

import ReactDOM from 'react-dom';

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

3
Estoy usando declaraciones de importación en webpack y todavía recibo este error. Pensé que webpack se encargaría del orden de carga de los scripts, ¿no?
thetrystero

44
Considere usar aplazar <script defer src = " fb.me/react-0.14.7.js " ></script> <script defer src =" fb.me/react-dom-0.14.7.js"></ script > <! - su código de aplicación ahora -> <script defer src = "app.js"> </script> </body>
aterrizó

44
@thetrystero No, webpack no tiene conocimiento sobre el lugar relativo del paquete de su aplicación para los nodos DOM en los que opera.
Dan Abramov

1
Tal error críptico - sólo poner escritura abajo div raíz hizo trabajar ...
kchoi

1
No es el caso de @DanAbramov, pero recibí el mismo error al usar un contenedor de destino sin una etiqueta de cierre completa (por ejemplo <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 +)

Nota : Tener <script async src="..."></script>en el encabezado asegura que el navegador comenzará a descargar el paquete de JavaScript antes de cargar el contenido HTML.

Fuente: React Starter Kit , cargador de estilo isomorfo


55
Es en ReactDOM.renderlugar de React.render.
Conrado Fonseca

Nota de advertencia: si configura su reacción para que se cargue de forma asincrónica, se crea una condición de carrera: si el navegador termina de analizar la página antes de que se ejecute el JS, está bien. Si el JS se carga antes de analizar la página, terminará con el mismo problema sobre el que trata la pregunta. deferpuede ser una mejor opción
BRasmussen

16

la función ready se puede usar así:

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

Si no desea usar jQuery, puede usar la onloadfunción:

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

66
Creo que DOMContentLoadedsería más apropiado incluso para manejar que load(esto es lo que usa jQuery ). También puede hacer esto en JS con window.addEventListener, sin necesidad de controladores en línea y funciones globales.
Dan Abramov

3
Tenga en cuenta que renderComponent se amortizará. Utilice React.render () en su lugar.
Tommyixi

2
Estoy usando react-rails, por lo que mover la etiqueta del script a la parte inferior de la etiqueta del cuerpo no era una opción. $(document).readyresuelve el problema. Ah y sí, use en renderlugar de renderComponent.
ltrainpr

1
Es una práctica extremadamente mala usar jQuery con React. Use cualquiera, pero no ambos al mismo tiempo.
agregado1166877

11

solo una conjetura, ¿qué tal si agregamos a index.html lo siguiente:

type="javascript"

Me gusta esto:

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

¡Para mí funcionó! :-)


3
Solo para tu información, esto me causó problemas donde type="text/javascript"funcionó correctamente.
steezeburger

Eso es terrible, en realidad se solucionó mi problema. un poco triste, pero no estoy seguro de quién culpar a este, reaccionar o babel?
William Howley

6

Me encontré con el mismo error. Resultó ser causado por un simple error tipográfico después de cambiar mi código de:

document.getElementById('root')

a

document.querySelector('root')

Observe el '#' que falta. Debería haber sido

document.querySelector('#root')

Solo publica en caso de que ayude a alguien más a resolver este error.


4

Sí, básicamente lo que hizo es correcto, excepto que olvida que JavaScript está sincronizado en muchos casos, por lo que ejecuta el código antes de que se cargue su DOM , hay pocas maneras de resolver esto:

1) Verifique si DOM está completamente cargado, luego haga lo que quiera, puede escuchar DOMContentLoaded, por ejemplo:

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

2) Una forma muy común es agregar la etiqueta del script en la parte inferior de su document(después de la etiqueta del cuerpo):

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

3) Uso window.onload, que se activa cuando se carga toda la página (img, etc.)

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

4) Uso document.onload, que se dispara cuando el DOM está listo:

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

Incluso hay más opciones para verificar si DOM está listo, pero la respuesta corta es NO ejecutar ningún script antes de asegurarse de que su DOM esté listo en todos los casos ...

JavaScript funciona junto con elementos DOM y si no están disponibles, devolverá nulo , podría romper toda la aplicación ... así que siempre asegúrese de estar completamente listo para ejecutar su JavaScript antes de hacerlo ...


2

Si usa webpack para representar su reacción y usa HtmlWebpackPlugin en su reacción, este complemento construye su index.html en blanco por sí mismo e inyecta el archivo js en él, por lo que no contiene el elemento div, ya que HtmlWebpackPlugin documenta puede crear su propio índice. html y dar su dirección a este complemento, en mi webpack.config.js

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

y este es mi archivo 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
¿Por qué usar el HtmlWebpackPlugincomplemento aquí si se usa para hacer referencia al archivo HTML estático?
Harry Cho

1

En mi caso, este error fue causado por la recarga en caliente, al introducir nuevas clases. En esa etapa del proyecto, use observadores normales para compilar su código.


1

Para aquellos que usan ReactJS.Net y obtienen este error después de una publicación:

Verifique las propiedades de sus archivos .jsx y asegúrese de que Build Actionesté configurado en Content. Los establecidos para Noneno serán publicados. Encontré esta solución a partir de esta respuesta SO .


1

Me encontré con un mensaje de error similar / similar. En mi caso, no tenía el nodo DOM de destino que representa el componente ReactJS definido. Asegúrese de que el nodo de destino HTML esté bien definido con "id" o "nombre" apropiados, junto con otros atributos HTML (adecuados para su necesidad de diseño)


Tuve un problema similar. En vista, tenía la instrucción <code> if </code> donde el elemento objetivo esperado debería generarse si se cumplía la condición. En mi caso, el elemento adecuado no se procesó debido a la condición, sino que el script se ejecutó e intentó montar el componente en el elemento que no existía en DOM.
Rafal Cypcer

0

es fácil simplemente hacer HTML CSS básico js y renderizar el script desde 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

Cuando tienes:

Error: Error no detectado: el contenedor de destino no es un elemento DOM.

Puede usar el evento DOMContentLoaded o mover su <script ...></script>etiqueta en la parte inferior de su cuerpo.

El evento DOMContentLoaded se desencadena cuando el documento HTML inicial se ha cargado y analizado por completo, sin esperar a que las hojas de estilo, las imágenes y los subtramas terminen de cargarse.

document.addEventListener("DOMContentLoaded", function(event) {
  ReactDOM.render(<App />, document.getElementById('root'));
})
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.