Violação invariável: _registerComponent (…): o contêiner de destino não é um elemento DOM


388

Eu recebo esse erro após uma página de exemplo trivial de React:

Erro não capturado: Violação invariável: _registerComponent (...): O contêiner de destino não é um elemento DOM.

Aqui está o meu 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>

O que isto significa?


8
@ go-oleg: Esta é uma notação curta do ES6. Não é o problema, porque o react-tools possui o transpiler ES6. Veja aqui
Dan Abramov

14
Corri para o mesmo erro e, como outros sugeriram, é porque o arquivo bundle.js está carregando muito cedo. Mova sua tag <script> para o corpo (como a última linha antes da tag de fechamento </body>) para resolver esse erro.
Todd R

2
se isso não ajudar aqui
daslicht

@daslicht Espero que você tenha encontrado sua resposta, mas apenas para dizer: VERIFIQUE DUPLO se você não está misturando classes e identidades. document.getElementById ("foo") nunca vai encontrar uma tag que leia <div class = "foo">
Dave Kanter

Respostas:


626

No momento em que o script é executado, o documentelemento ainda não está disponível, porque scriptestá no diretório head. Embora seja uma solução válida para manter scriptem heade rende no DOMContentLoadedevento , é ainda melhor para colocar o seu scriptna parte inferior do body e tornar componente raiz para um divantes assim:

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

e no bundle.js, ligue para:

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

Você deve sempre renderizar para um aninhado em divvez de body.Caso contrário, todos os tipos de código de terceiros (Google Font Loader, plug-ins de navegador, o que for) podem modificar o bodynó DOM quando o React não o espera e causar erros estranhos que são muito difíceis de rastrear e depurar.Leia mais sobre esse problema.

O bom de colocar script na parte inferior é que ele não bloqueará a renderização até o carregamento do script, caso você adicione a renderização do servidor React ao seu projeto.


Atualização: (07 de outubro de 2015 | v0.14 )

React.render está obsoleto, use ReactDOM.render vez disso.

Exemplo:

import ReactDOM from 'react-dom';

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

3
Estou usando instruções de importação no webpack e ainda recebo esse erro. Eu pensei que o webpack vai cuidar da ordem de carregar scripts não?
thetrystero

4
Considere usar defer <script defer src = " fb.me/react-0.14.7.js " ></script> <script defer src =" fb.me/react-dom-0.14.7.js"></ script > <! - seu código do aplicativo agora -> <script defer src = "app.js"> </script> </body>
chegou em

4
@thetrystero Não, o webpack não tem conhecimento sobre o local relativo do pacote do seu aplicativo em relação aos nós DOM em que opera.
Dan Abramov 11/04

11
Tal erro enigmática - apenas colocando script abaixo div raiz fez funcionar ...
kchoi

11
Não é o caso de @DanAbramov mas eu recebi o mesmo erro usando um recipiente de destino sem uma marca de fechamento completo (por exemplo, <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 : Ter <script async src="..."></script>no cabeçalho garante que o navegador comece a baixar o pacote JavaScript antes de conteúdo HTML seja carregado.

Fonte: React Starter Kit , carregador de estilo isomórfico


5
É ao ReactDOM.renderinvés de React.render.
Conrado Fonseca

Nota de aviso: se você configurar o seu reag para carregar de forma assíncrona, ele criará uma condição de corrida - se o navegador terminar de analisar a página antes da execução do JS, você estará bem. Se o JS for carregado antes da análise da página, você terminará com o mesmo problema de que trata a questão. deferpode ser uma opção melhor
BRasmussen

16

a função ready pode ser usada assim:

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

Se você não quiser usar o jQuery, poderá usar a onloadfunção:

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

6
Eu acho DOMContentLoadedque seria mais apropriado manipular do que load(isso é o que o jQuery usa ). Você também pode fazer isso em JS com window.addEventListener, sem necessidade de manipuladores embutidos e funções globais.
Dan Abramov

3
Observe que renderComponent será depreciado. Use React.render ().
21715 Tommyixi

2
Como estou usando o react-rails, mover a tag de script para a parte inferior da tag body não era uma opção. $(document).readyresolveu o problema. Ah e sim, use em rendervez de renderComponent.
Ltrainpr 17/07/2015

11
É uma prática extremamente ruim usar o jQuery com o React. Use um dos dois, mas não os dois ao mesmo tempo.
aggregate1166877

11

apenas um palpite, que tal adicionar ao index.html o seguinte:

type="javascript"

como isso:

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

Para mim funcionou! :-)


3
Apenas para sua informação, isso causou problemas para mim, onde type="text/javascript"funcionou corretamente.
steezeburger

Isso é terrível, na verdade, foi corrigido o meu problema. meio triste, mas não tenho certeza de quem culpar, reagir ou babel?
precisa

6

Corri para o mesmo erro. Acabou sendo causado por um erro de digitação simples depois de alterar meu código de:

document.getElementById('root')

para

document.querySelector('root')

Observe o '#' ausente. Deveria ter sido

document.querySelector('#root')

Apenas postando caso ajude alguém a resolver esse erro.


4

Sim, basicamente o que você fez é certo, exceto que você esquece que o JavaScript é sincronizado em muitos casos, então você executa o código antes do seu DOM carregamento do , existem algumas maneiras de resolver isso:

1) Verifique se o DOM está totalmente carregado e faça o que quiser. Você pode ouvir DOMContentLoaded, por exemplo:

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

2) A maneira mais comum é adicionar a tag de script na parte inferior do seu document(após a tag body):

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

3) Utilização window.onload, que é acionada quando a página inteira é carregada (img, etc)

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

4) Using document.onload, que é acionado quando o DOM está pronto:

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

Existem ainda mais opções para verificar se o DOM está pronto, mas a resposta curta é NÃO executar nenhum script antes de verificar se o DOM está pronto em todos os casos ...

O JavaScript está funcionando junto com os elementos DOM e, se não estiverem disponíveis, retornará nulo , poderá interromper o aplicativo inteiro ... portanto, verifique sempre se você está totalmente pronto para executar o JavaScript antes de executar ...


2

Se você usa o webpack para renderizar o seu react e usa o HtmlWebpackPlugin no seu react, esse plug-in cria seu próprio index.html em branco e injeta o arquivo js nele, para que ele não contenha elemento div, como o HtmlWebpackPlugin documenta, você pode criar seu próprio índice. html e forneça o endereço desse plug-in no meu webpack.config.js

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

e este é o meu arquivo 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>

11
Por que usar o HtmlWebpackPluginplugin aqui se ele é usado para fazer referência a arquivos HTML estáticos?
Harry Cho

1

No meu caso, esse erro foi causado pelo recarregamento a quente, ao introduzir novas classes. Nesse estágio do projeto, use observadores normais para compilar seu código.


1

Para aqueles que usam o ReactJS.Net e obtêm esse erro após uma publicação:

Verifique as propriedades dos seus arquivos .jsx e verifique se Build Actionestá definido como Content. Aqueles definidos como Nonenão serão publicados. Encontrei esta solução com esta resposta SO .


1

Corri para a mesma / mesma mensagem de erro. No meu caso, eu não tinha o nó DOM de destino que deve renderizar o componente ReactJS. Verifique se o nó de destino HTML está bem definido com o "id" ou "nome" apropriado, juntamente com outros atributos HTML (adequados para sua necessidade de design)


Eu tive um problema semelhante. Em vista, eu tinha a instrução <code> if </code> onde o elemento de destino esperado deveria ser gerado se a condição fosse atendida. No meu caso, o elemento apropriado não foi renderizado por causa da condição, mas o script foi executado e tentou montar o componente no elemento que não existia no DOM.
Rafal Cypcer

0

é fácil, basta criar js CSS HTML básicos e renderizar o script de 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 você conseguiu:

Erro: Erro não capturado: o contêiner de destino não é um elemento DOM.

Você pode usar o evento DOMContentLoaded ou mover sua <script ...></script>tag na parte inferior do seu corpo.

O evento DOMContentLoaded é acionado quando o documento HTML inicial foi completamente carregado e analisado, sem aguardar que folhas de estilo, imagens e sub-quadros terminem de carregar.

document.addEventListener("DOMContentLoaded", function(event) {
  ReactDOM.render(<App />, document.getElementById('root'));
})
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.