불변 위반 : _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

14
이 같은 오류가 발생하여 다른 사람들이 제안했듯이 bundle.js 파일이 너무 일찍로드되기 때문입니다. 이 오류를 해결하려면 <script> 태그를 본문 (닫는 </ body> 태그 앞의 마지막 줄)으로 이동하십시오.
Todd R

2
그건 도움이되지 않습니다
daslicht

@daslicht 나는 당신이 당신의 대답을 찾았기를 바랍니다 : 그러나 그것은 말하기 : DOUBLE CHECK 당신은 클래스와 아이디를 섞지 않는다는 것을 확인하십시오. document.getElementById ( "foo")는 결코 <div class = "foo">라는 태그를 찾지 못할 것입니다
Dave Kanter

답변:


625

스크립트가 실행될 때 documentelement script자체는에 있기 때문에 아직 사용할 수 없습니다 head. 그것을 유지하는 유효한 해결책 반면 scripthead렌더링 DOMContentLoaded이벤트 , 그것은 심지어 더 나은 당신을 넣어 script의 맨 아래에 body A를 루트 요소를 렌더링 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, 브라우저 플러그인 등)는 bodyReact가 예상하지 않을 때 DOM 노드를 수정할 수 있으며 추적 및 디버그가 매우 어려운 이상한 오류를 일으킬 수 있습니다. 이 문제에 대해 자세히 알아보십시오.

script맨 아래 에 배치하는 좋은 점은 프로젝트에 React 서버 렌더링을 추가하는 경우 스크립트가로드 될 때까지 렌더링을 차단하지 않는다는 것입니다.


업데이트 : (2015 년 10 월 7 일 | v0.14 )

React.render더 이상 사용되지 않습니다 ReactDOM.render . 대신 사용하십시오.

예:

import ReactDOM from 'react-dom';

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

3
webpack에서 import 문을 사용하고 있는데 여전히이 오류가 발생합니다. 웹팩이 스크립트로드 순서를 처리한다고 생각 했습니까?
thetrystero

4
지연 <script 지연 src = " fb.me/react-0.14.7.js " ></script> <script 지연 src =" fb.me/react-dom-0.14.7.js ">< / script > <!-지금 앱 코드-> <script defer src = "app.js"> </ script> </ body>
도착

4
@thetrystero 아니요, webpack은 애플리케이션 번들이 작동하는 DOM 노드에 대한 애플리케이션 번들의 상대적 위치에 대해 알지 못합니다.
Dan Abramov

1
이러한 비밀스러운 오류-루트 div 아래에 스크립트를 넣으면 작동합니다 ...
kchoi

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>헤더에 있으면 HTML 컨텐츠가로드 되기 전에 브라우저가 JavaScript 번들 다운로드를 시작 합니다.

출처 : React Starter Kit , 동형 스타일 로더


5
그것은입니다 ReactDOM.render대신 React.render.
Conrado Fonseca

경고 참고 : 반응이 비동기 적으로로드되도록 설정하면 경쟁 조건이 발생합니다 .JS가 실행되기 전에 브라우저가 페이지 구문 분석을 마치면 괜찮습니다. 페이지가 파싱되기 전에 JS 가로 드되면 질문과 동일한 문제가 발생합니다. defer더 나은 옵션 일 수 있습니다
BRasmussen

16

준비 기능은 다음과 같이 사용할 수 있습니다 :

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

jQuery를 사용하지 않으려면 다음 onload함수를 사용할 수 있습니다 .

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

6
나는 ( jQuery가 사용 하는 DOMContentLoaded것보다) 처리하는 것이 더 적절 하다고 생각 합니다 . 인라인 핸들러와 전역 함수가 없어도 JS에서이 작업을 수행 할 수도 있습니다. loadwindow.addEventListener
Dan Abramov

3
renderComponent는 감가 상각됩니다. 대신 React.render ()를 사용하십시오.
Tommyixi

2
반응 레일을 사용하고 있으므로 스크립트 태그를 본문 태그의 맨 아래로 이동하는 것은 옵션이 아닙니다. $(document).ready문제를 해결했다. 아 render대신 사용 합니다 renderComponent.
ltrainpr

1
jQuery를 React와 함께 사용하는 것은 매우 나쁜 습관입니다. 둘 중 하나만 사용하십시오.
집합

11

간단히 추측하면 index.html에 다음을 추가하는 방법은 다음과 같습니다.

type="javascript"

이처럼 :

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

나를 위해 그것은 효과가 있었다! :-)


3
참고로, type="text/javascript"제대로 작동하는 곳에서 문제가 발생 했습니다.
steezeburger

실제로 내 문제가 해결 된 것은 끔찍합니다. 슬프지만 누가이 일에 책임이 있는지, 확실하지 않은지, 반응을 보입니까?
William Howley

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) 가장 일반적인 방법은 스크립트 태그를 document(바디 태그 뒤에) 하단에 추가하는 것입니다 .

<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

반응을 렌더링하기 위해 웹팩을 사용하고 반응에서 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 파일을 참조하는 데 플러그인을 사용하는 이유는 무엇 입니까?
Harry Cho

1

필자의 경우이 오류는 새로운 클래스를 도입하는 동안 핫 리로드로 인해 발생했습니다. 프로젝트의 해당 단계에서 일반 감시자를 사용하여 코드를 컴파일하십시오.


1

ReactJS.Net을 사용하고 게시 후이 오류가 발생하는 경우 :

.jsx 파일의 속성을 확인하고 Build Action로 설정되어 있는지 확인하십시오 Content. 설정 한 내용 None은 게시되지 않습니다. 이 SO 답변 에서이 솔루션을 찾았습니다 .


1

비슷한 / 같은 오류 메시지가 나타났습니다. 필자의 경우 ReactJS 구성 요소를 정의 할 대상 DOM 노드가 없었습니다. HTML 대상 노드가 다른 HTML 속성과 함께 적절한 "id"또는 "name"으로 잘 정의되어 있는지 확인하십시오 (디자인 요구에 적합)


비슷한 문제가있었습니다. 보기에는 조건이 충족되면 예상 대상 요소가 생성되어야하는 <code> if </ code> 문이 있습니다. 필자의 경우 조건으로 인해 적절한 요소가 렌더링되지 않았지만 스크립트가 실행되어 DOM에 존재하지 않는 요소에 구성 요소를 마운트하려고했습니다.
Rafal Cypcer

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

당신이 얻을 때 :

오류 : catch되지 않은 오류 : 대상 컨테이너가 DOM 요소가 아닙니다.

DOMContentLoaded 이벤트 를 사용 하거나 <script ...></script>몸의 맨 아래로 태그를 이동할 수 있습니다 .

DOMContentLoaded 초기 HTML 문서가 완전히 마무리 로딩에 스타일 시트, 이미지 및 서브 프레임을 기다리지 않고,로드 및 구문 분석 된 이벤트가 발생합니다.

document.addEventListener("DOMContentLoaded", function(event) {
  ReactDOM.render(<App />, document.getElementById('root'));
})
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.