Нарушение инварианта: _registerComponent (…): целевой контейнер не является элементом DOM

352

Я получаю эту ошибку после создания тривиальной страницы примера 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>

Что это значит?

  • 7
    @ go-oleg: это краткая запись ES6. Это не проблема, потому что у реакционных инструментов есть транспортер ES6. Посмотреть здесь
  • 13
    Я столкнулся с той же ошибкой, и, как другие предположили, это потому, что ваш файл bundle.js загружается слишком рано. Переместите свой тег <script> в тело (как последняя строка перед закрывающим тегом </ body>), чтобы устранить эту ошибку.
Показать ещё 2 комментария
Теги:
dom

10 ответов

594
Лучший ответ

К моменту выполнения скрипта элемент document еще не доступен, поскольку сам script находится в head. Хотя это правильное решение для сохранения script в head и рендеринга по событию DOMContentLoaded, еще лучше поместить ваш script в самый DOMContentLoaded 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. В противном случае все виды стороннего кода (Google Font Loader, плагины для браузера и т.д.) Могут изменять узел DOM body когда React его не ожидает, и вызывать странные ошибки, которые очень сложно отследить и отладить. Узнайте больше об этой проблеме.

Хорошая вещь в размещении script внизу - он не блокирует рендеринг до загрузки скрипта, если вы добавите рендеринг сервера React в свой проект.


Обновление: (07 октября 2015 | v0.14)

React.render устарел, вместо этого используйте ReactDOM.render.

Пример:

import ReactDOM from 'react-dom';

ReactDOM.render(<App />, document.getElementById('root'));
  • 2
    Я использую операторы импорта в веб-пакете и все еще получаю эту ошибку. Я думал, что webpack позаботится о порядке загрузки скриптов нет?
  • 4
    Рекомендуется использовать defer <script defer src = " fb.me/react-0.14.7.js" ></script> <script defer src =" fb.me/react-dom-0.14.7.js"></ script > <! - код вашего приложения сейчас -> <script defer src = "app.js"> </ script> </ body>
Показать ещё 4 комментария
50

/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 Starter Kit, isomorphic-style-loader

  • 5
    Это ReactDOM.render вместо React.render .
  • 0
    Предупреждение: если вы устанавливаете реакцию на загрузку асинхронно, это создает условие гонки - если браузер заканчивает анализ страницы до выполнения JS, все в порядке. Если JS загружается до того, как страница проанализирована, вы столкнетесь с той же проблемой, о которой идет речь. defer может быть лучшим вариантом
15

функция готовности может быть использована следующим образом:

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

Если вы не хотите использовать jQuery, вы можете использовать функцию onload:

<body onload="initReact()">...</body>
  • 5
    Я думаю, что DOMContentLoaded будет более подходящим даже для обработки, чем для load (это то, что использует jQuery ). Вы также можете сделать это в JS с помощью window.addEventListener , без необходимости использования встроенных обработчиков и глобальных функций.
  • 3
    Обратите внимание, что renderComponent будет амортизироваться. Вместо этого используйте React.render ().
Показать ещё 1 комментарий
9

просто дикая догадка, как насчет добавления в index.html следующего:

type="javascript"

вот так:

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

Для меня это сработало!: -)

  • 2
    Просто к вашему сведению, это вызвало у меня проблемы, когда type="text/javascript" работал правильно.
  • 0
    Это ужасно, что на самом деле исправил мою проблему. отчасти грустно, но не уверен, кто виноват в этом, реагировать или вавилон?
3

Я столкнулся с той же ошибкой. Это оказалось вызвано простой опечаткой после изменения моего кода с:

document.getElementById('root')

в

document.querySelector('root')

Обратите внимание на пропущенный '#' Это должно было быть

document.querySelector('#root')

Просто публикация на случай, если это поможет кому-либо еще решить эту ошибку.

3

Да, в основном то , что вы сделали, правильно, за исключением того, что вы забыли, что 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, прежде чем делать это...

1

Я столкнулся с похожим/тем же сообщением об ошибке. В моем случае у меня не было целевой DOM node, который должен отображать компонент ReactJS. Убедитесь, что цель HTML node четко определена с помощью соответствующего "id" или "name", а также других атрибутов HTML (подходящих для вашего дизайна)

  • 0
    У меня была похожая проблема. В связи с этим у меня был оператор <code> if </ code>, в котором должен быть создан ожидаемый целевой элемент, если условие было выполнено. В моем случае надлежащий элемент не отображался из-за условия, но скрипт выполнялся и пытался смонтировать компонент на элементе, который не существует в DOM.
1

В моем случае эта ошибка была вызвана горячей перезагрузкой при введении новых классов. На этом этапе проекта используйте обычные наблюдатели для компиляции кода.

0

использовать эти src dom в файле index.html, а затем связать с файлом js

  • 1
    Хотя это может ответить на вопрос, предоставление дополнительного контекста относительно того, как и / или почему оно решает проблему, улучшило бы долгосрочную ценность ответа.
0

Для тех, кто использует ReactJS.Net и получает эту ошибку после публикации:

Проверьте свойства ваших .jsx файлов и убедитесь, что для параметра Build Action установлено значение Content. Те, которые установлены в None, не будут опубликованы. Я пришел к этому решению из этого SO-ответа.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню