Violazione invariante: _registerComponent (…): il contenitore di destinazione non è un elemento DOM


388

Ottengo questo errore dopo aver reso banale la pagina di esempio di React:

Errore non rilevato: violazione invariante: _registerComponent (...): il contenitore di destinazione non è un elemento DOM.

Ecco il mio codice:

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

Cosa significa questo?


8
@ go-oleg: questa è la notazione breve ES6. Non è questo il problema perché reagire-strumenti ha transpiler ES6. Vedi qui
Dan Abramov,

14
Ho riscontrato questo stesso errore e, come altri hanno suggerito, è perché il file bundle.js si sta caricando troppo presto. Sposta il tag <script> nel corpo (come ultima riga prima del tag di chiusura </body>) per risolvere questo errore.
Todd R,

2
questo non aiuta qui
daslicht

@daslicht Spero che tu abbia trovato la tua risposta, ma solo così si dice: DOUBLE CHECK che non stai mescolando classi e ID. document.getElementById ("foo") non troverà mai, mai e poi mai, un tag che legge <div class = "foo">
Dave Kanter,

Risposte:


626

Quando viene eseguito lo script, l' documentelemento non è ancora disponibile, poiché esso scriptstesso è nel file head. Sebbene sia una soluzione valida da tenere scriptin considerazione heade renderizzare in DOMContentLoadedcaso di evento , è ancora meglio mettere scriptin fondo il componente root body e renderizzare un componente root divprima che sia così:

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

e nel bundle.js, chiama:

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

Dovresti sempre eseguire il rendering su un nidificato divanziché body. Altrimenti, ogni sorta di codice di terze parti (Google Font Loader, plugin del browser, qualunque cosa) può modificare il bodynodo DOM quando React non se lo aspetta e causare strani errori che sono molto difficili da rintracciare ed eseguire il debug. Ulteriori informazioni su questo problema.

La cosa bella di mettere scriptin fondo è che non bloccherà il rendering fino al caricamento dello script nel caso in cui aggiungi il rendering del server React al tuo progetto.


Aggiornamento: (07 ottobre 2015 | v0.14 )

React.renderè deprecato, utilizzare ReactDOM.render invece.

Esempio:

import ReactDOM from 'react-dom';

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

3
Sto usando le dichiarazioni di importazione nel webpack e continuo a ricevere questo errore. Pensavo che il webpack si occuperà dell'ordine di caricamento degli script no?
thetrystero,

4
Considera di utilizzare defer <script defer src = " fb.me/react-0.14.7.js " ></script> <script defer src =" fb.me/react-dom-0.14.7.js"></ script > <! - il codice della tua app ora -> <script defer src = "app.js"> </script> </body>
sbarcato il

4
@thetrystero No, webpack non è a conoscenza della posizione relativa del bundle dell'applicazione rispetto ai nodi DOM su cui opera.
Dan Abramov,

1
Tale errore criptico - solo mettere script sotto root div lo ha fatto funzionare ...
kchoi il

1
Non è il caso di @DanAbramov ma ho ricevuto lo stesso errore utilizzando un contenitore di destinazione senza un tag di chiusura completo (ad esempio <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 : <script async src="..."></script>la presenza nell'intestazione garantisce che il browser inizierà a scaricare il pacchetto JavaScript prima che venga caricato il contenuto HTML.

Fonte: React Starter Kit , caricatore di stile isomorfo


5
È ReactDOM.renderinvece di React.render.
Conrado Fonseca,

Nota di avviso: se imposti la reazione in modo che si carichi in modo asincrono, si crea una condizione di competizione. Se il browser termina l'analisi della pagina prima dell'esecuzione di JS, stai bene. Se JS viene caricato prima che la pagina venga analizzata, si otterrà lo stesso problema della domanda. deferpotrebbe essere un'opzione migliore
BRasmussen,

16

la funzione pronto può essere utilizzata in questo modo:

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

Se non si desidera utilizzare jQuery, è possibile utilizzare la onloadfunzione:

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

6
Penso che DOMContentLoadedsarebbe più appropriato persino gestirlo di load(questo è ciò che utilizza jQuery ). Puoi anche farlo in JS con window.addEventListener, senza bisogno di gestori in linea e funzioni globali.
Dan Abramov,

3
Nota, renderComponent sarà ammortizzato. Utilizzare invece React.render ().
Tommyixi,

2
Sto usando i rotaie di reazione, quindi spostare il tag script nella parte inferiore del tag body non era un'opzione. $(document).readyproblema risolto. Oh e sì usare renderinvece di renderComponent.
ltrainpr,

1
È una pessima pratica usare jQuery con React. Utilizzare entrambi, ma non entrambi contemporaneamente.
aggregate1166877,

11

solo un'ipotesi selvaggia, che ne dici di aggiungere a index.html quanto segue:

type="javascript"

come questo:

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

Per me ha funzionato! :-)


3
Cordiali saluti, questo ha causato problemi per me come type="text/javascript"funzionava correttamente.
steezeburger,

Questo è terribile che in realtà ha risolto il mio problema. un po 'triste, ma non sei sicuro di chi dare la colpa a questo, reagire o fare la babele?
William Howley,

6

Ho riscontrato lo stesso errore. Si è scoperto essere causato da un semplice errore di battitura dopo aver cambiato il mio codice da:

document.getElementById('root')

per

document.querySelector('root')

Notare il '#' mancante avrebbe dovuto essere

document.querySelector('#root')

Basta pubblicare nel caso in cui aiuti gli altri a risolvere questo errore.


4

Sì, sostanzialmente quello che hai fatto è giusto, tranne che dimentichi che JavaScript è sincronizzato in molti casi, quindi esegui il codice prima che il DOM venga caricato, ci sono alcuni modi per risolverlo:

1) Verifica se DOM è completamente caricato, quindi fai quello che vuoi, ad esempio puoi ascoltare DOMContentLoaded :

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

2) Un modo molto comune è l'aggiunta del tag script nella parte inferiore del tuo document(dopo il tag body):

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

3) Utilizzo window.onload, che viene generato quando l'intera pagina viene caricata (img, ecc.)

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

4) Utilizzo document.onload, che viene attivato quando il DOM è pronto:

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

Esistono ancora più opzioni per verificare se DOM è pronto, ma la risposta breve è NON eseguire alcuno script prima di assicurarsi che il DOM sia pronto in ogni caso ...

JavaScript funziona insieme agli elementi DOM e, se non sono disponibili, restituirà null , potrebbe interrompere l'intera applicazione ... quindi assicurati sempre di essere pronto per eseguire il tuo JavaScript prima di farlo ...


2

Se si utilizza il webpack per il rendering della propria reazione e si utilizza HtmlWebpackPlugin nella propria reazione, questo plug-in crea il suo indice.html vuoto da solo e inietta il file js in esso, quindi non contiene l'elemento div, in quanto i documenti HtmlWebpackPlugin possono creare il proprio indice. html e dai il suo indirizzo a questo plugin, nel mio webpack.config.js

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

e questo è il mio file 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
Perché usare il HtmlWebpackPluginplugin qui se viene utilizzato per fare riferimento a file HTML statico?
Harry Cho,

1

Nel mio caso questo errore è stato causato dalla ricarica a caldo, durante l'introduzione di nuove classi. In quella fase del progetto, usa normali osservatori per compilare il tuo codice.


1

Per coloro che utilizzano ReactJS.Net e ottengono questo errore dopo una pubblicazione:

Controlla le proprietà dei tuoi file .jsx e assicurati che Build Actionsia impostato su Content. Quelli impostati su Nonenon saranno pubblicati. Ho trovato questa soluzione da questa risposta SO .


1

Ho riscontrato un messaggio di errore simile / uguale. Nel mio caso, non avevo il nodo DOM di destinazione che deve rendere definito il componente ReactJS. Assicurati che il nodo di destinazione HTML sia ben definito con "id" o "nome" appropriati, insieme ad altri attributi HTML (adatti alle tue esigenze di progettazione)


Ho avuto un problema simile. In vista avevo l'istruzione <code> if </code> in cui l'elemento target atteso doveva essere generato se la condizione fosse soddisfatta. Nel mio caso, l'elemento corretto non è stato reso a causa della condizione, ma lo script è stato eseguito e ha cercato di montare un componente su un elemento che non esisteva in DOM.
Rafal Cypcer,

0

è facile semplicemente creare js CSS HTML di base e renderizzare lo script da 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

Quando hai ottenuto:

Errore: errore non rilevato: il contenitore di destinazione non è un elemento DOM.

Puoi utilizzare l' evento DOMContentLoaded o spostare il <script ...></script>tag nella parte inferiore del corpo.

L' evento DOMContentLoaded viene generato quando il documento HTML iniziale è stato completamente caricato e analizzato, senza attendere il completamento del caricamento di fogli di stile, immagini e sottoframe.

document.addEventListener("DOMContentLoaded", function(event) {
  ReactDOM.render(<App />, document.getElementById('root'));
})
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.