การละเมิดที่ไม่เปลี่ยนแปลง: _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 มันไม่ได้เป็นปัญหาเพราะเครื่องมือตอบโต้มีทรานสฟิลเลอร์ ES6 ดูที่นี่
Dan Abramov

14
ฉันพบข้อผิดพลาดเดียวกันนี้และอย่างที่คนอื่น ๆ แนะนำเพราะไฟล์ bundle.js ของคุณโหลดเร็วเกินไป ย้ายแท็ก <script> ของคุณไปไว้ในเนื้อความ (เป็นบรรทัดสุดท้ายก่อนแท็กปิด </body>) เพื่อแก้ไขข้อผิดพลาดนี้
ทอดด์ R

2
นั่นไม่ได้ช่วยที่นี่
daslicht

@daslicht ฉันหวังว่าคุณจะพบคำตอบของคุณ แต่เพียงอย่างเดียวก็บอกว่า: ตรวจสอบสองครั้งที่คุณไม่ได้ผสมชั้นเรียนและรหัสของ document.getElementById ("foo") จะไม่เคยเคยไปหาแท็กที่อ่าน <div class = "foo">
Dave Kanter

คำตอบ:


625

โดยสคริปต์เวลาที่จะดำเนินการdocumentองค์ประกอบยังไม่สามารถใช้ได้เพราะตัวเองอยู่ในscript headขณะที่มันเป็นวิธีการแก้ปัญหาที่ถูกต้องที่จะให้scriptในheadและแสดงผลในDOMContentLoadedเหตุการณ์ก็จะยิ่งดีกว่าที่จะใส่ของคุณscriptที่ด้านล่างสุดของ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, เบราว์เซอร์ปลั๊กอิน, อะไรก็ตาม) สามารถแก้ไขbodyโหนด DOM เมื่อ React ไม่ได้คาดหวังและทำให้เกิดข้อผิดพลาดแปลก ๆ ที่ยากต่อการติดตามและแก้ไข อ่านเพิ่มเติมเกี่ยวกับปัญหานี้

สิ่งที่ดีเกี่ยวกับการวางscriptที่ด้านล่างคือมันจะไม่ปิดกั้นการแสดงผลจนกว่าจะโหลดสคริปต์ในกรณีที่คุณเพิ่มการแสดงผลของเซิร์ฟเวอร์ React ในโครงการของคุณ


อัปเดต: (07 ตุลาคม 2558 | v0.14 )

React.renderเลิกใช้แล้วใช้ReactDOM.render แทน

ตัวอย่าง:

import ReactDOM from 'react-dom';

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

3
ฉันใช้คำสั่งการนำเข้าใน webpack และยังได้รับข้อผิดพลาดนี้ ฉันคิดว่า webpack จะดูแลลำดับการโหลดสคริปต์หรือไม่
thetrystero

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 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>ส่วนหัวให้แน่ใจว่าเบราว์เซอร์จะเริ่มดาวน์โหลดชุด JavaScript ก่อนที่จะโหลดเนื้อหา HTML

ที่มา: React Starter Kit , isomorphic-style-loader


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
ฉันคิดว่าDOMContentLoadedจะเหมาะสมกว่าที่จะจัดการมากกว่าload(นี่คือสิ่งที่jQuery ใช้ ) คุณยังสามารถทำสิ่งนี้ใน JS ด้วยwindow.addEventListener, ไม่จำเป็นสำหรับฟังก์ชั่นอินไลน์และฟังก์ชั่นระดับโลก
Dan Abramov

3
หมายเหตุ renderComponent จะถูกคิดค่าเสื่อมราคา ใช้ React.render () แทน
Tommyixi

2
ฉันใช้ react-rails ดังนั้นการย้ายแท็กสคริปต์ไปที่ด้านล่างของแท็ก body ไม่ใช่ตัวเลือก $(document).readyแก้ไขปัญหา โอ้และใช่ใช้แทนrender renderComponent
ltrainpr

1
เป็นวิธีปฏิบัติที่แย่มากในการใช้ jQuery กับ React ใช้อย่างใดอย่างหนึ่ง แต่ไม่ใช่ทั้งสองอย่างในเวลาเดียวกัน
รวม

11

เพียงแค่เดาอย่างถ่องแท้แล้วการเพิ่มไปยัง index.html ต่อไปนี้:

type="javascript"

แบบนี้:

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

สำหรับฉันมันใช้งานได้! :-)


3
เพียงแค่ FYI สิ่งนี้ทำให้เกิดปัญหากับฉันซึ่ง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

หากคุณใช้ webpack สำหรับการแสดงปฏิกิริยาของคุณและใช้ HtmlWebpackPlugin ในการตอบสนองของคุณปลั๊กอินนี้จะสร้าง index.html ที่ว่างเปล่าของมันเองและฉีดไฟล์ js ไว้ภายในดังนั้นมันจึงไม่มีองค์ประกอบ div เช่น HtmlWebpackPlugin docs ที่คุณสามารถสร้างดัชนีของคุณเอง 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

ฉันพบข้อความแสดงข้อผิดพลาดที่คล้ายกัน / เหมือนกัน ในกรณีของฉันฉันไม่ได้มีโหนด DOM เป้าหมายซึ่งจะแสดงองค์ประกอบ ReactJS ที่กำหนดไว้ ตรวจสอบให้แน่ใจว่าโหนดเป้าหมาย HTML นั้นถูกกำหนดอย่างดีพร้อมกับ "id" หรือ "ชื่อ" ที่เหมาะสมพร้อมกับคุณสมบัติ HTML อื่น ๆ (เหมาะสำหรับความต้องการในการออกแบบของคุณ)


ฉันมีปัญหาที่คล้ายกัน ในมุมมองฉันมี <code> ถ้า </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

เมื่อคุณได้รับ:

ข้อผิดพลาด: ข้อผิดพลาดที่ไม่ได้รับ: คอนเทนเนอร์เป้าหมายไม่ใช่องค์ประกอบ DOM

คุณสามารถใช้เหตุการณ์DOMContentLoadedหรือย้าย<script ...></script>แท็กของคุณที่ด้านล่างของร่างกายของคุณ

DOMContentLoadedเหตุการณ์ fires เมื่อเอกสาร HTML เบื้องต้นได้รับการโหลดอย่างสมบูรณ์และแยกวิเคราะห์โดยไม่ต้องรอ stylesheets, ภาพ, และ subframes กับการโหลดเสร็จ

document.addEventListener("DOMContentLoaded", function(event) {
  ReactDOM.render(<App />, document.getElementById('root'));
})
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.