Etusivu
» Perustieto
»
Miten korjata Target Container Is Not a DOM Element -virhe React 18:ssa
Miten korjata Target Container Is Not a DOM Element -virhe React 18:ssa
Tärkein korjaus on tämä: varmista, että arvo, jonka välität funktiolle createRoot(), on todellinen DOM-elementti, joka on jo olemassa. React 18:ssa normaali asiakaspuolen sisääntulopiste näyttää tältä:
import { createRoot } from 'react-dom/client';
import App from './App';
const container = document.getElementById('root');
if (!container) {
throw new Error('Root element not found');
}
const root = createRoot(container);
root.render(<App />);
Jos document.getElementById('root') palauttaa arvon null, tai jos vahingossa välität React-elementin, kuten <App />, funktiolle createRoot(), React ei voi luoda juurta ja voi ilmoittaa virheestä “Target container is not a DOM element.” Reactin oma createRoot-vianmääritysdokumentointi määrittelee virheen juuri näin: funktiolle createRoot välitetty arvo ei ole DOM-solmu.
Tämä opas alkaa tästä todennäköisestä syystä, ja käsittelee sitten ajoitusongelmia, React 18 -migraatiovirheitä, palvelinrenderöintiä, portaaleja, TypeScriptiä ja testiympäristöjä, jotta voit lopettaa etsimisen, kun löydät sovellukseesi sopivan tapauksen.
Vaihe 1: Todenna, mitä todellisuudessa välität funktiolle createRoot()
Ennen konfiguraation muuttamista, lokita kontaineri:
Jos konsoli tulostaa null, React ei ole se osa, joka epäonnistui ensin. Selain ei löytänyt elementtiä, jolla on tuo ID, kun koodisi suoritettiin. Reactin virallinen vianmääritysosa listaa ID-epäsovun ja suorituksen ennen DOM-solmun olemassaoloa yleisiksi syiksi.
Jos konsoli tulostaa jotain kuten <div id="root"></div>, kontaineri on olemassa, ja sinun tulisi siirtyä eteenpäin alla oleviin React API-, SSR-, portaali- tai ympäristötarkistuksiin.
Soveltuu, kun: virhe ilmenee välittömästi sovelluksen käynnistyksen aikana, erityisesti tiedostoissa main.jsx, index.jsx tai index.tsx.
Toimenpide: älä arvaile. Lokita tarkka arvo, joka välitetään funktiolle createRoot(). Jos se on null, korjaa syy DOM-hakuun epäonnistumiseen ennen komponenttikoodin koskemista.
AI-generoitu kuvitus React 18:n kontainerivirheestä kehittäjäkonsolissa. Se ei ole kuvakaappaus todellisesta sovelluksesta tai React DevToolsista.
Vaihe 2: Varmista, että HTML-ID vastaa JavaScript-hakua
Yksinkertaisin todellinen syy on epäsovitus HTML:n ja JavaScriptin välillä.
HTML-tiedostossasi voi olla:
<div id="app"></div>
kun Reactin sisääntulotiedosto hakee:
document.getElementById('root')
Näiden nimien on vastattava toisiaan. Muuta joko merkintää:
<div id="root"></div>
tai hakua:
const container = document.getElementById('app');
Reactin nykyinen createRoot-viite käyttää standardiesimerkkiä document.getElementById('root'), mutta root ei ole taianomainen vaadittu ID. Mitä tahansa todellista DOM-elementtiä voidaan käyttää juurikontainerina. Tärkeä ehto on, että elementti on olemassa ja että haku palauttaa sen.
Soveltuu, kun: olet äskettäin muuttanut HTML-mallia, migroinut Create React Appista Viteen tai toiseen bundleriin, upottanut Reactin olemassa olevaan palvelinrenderöityyn sivuun tai nimennyt mount-elementin uudelleen.
Toimenpide: etsi projektista sekä id="root" että getElementById('root'). Jos projekti käyttää tarkoituksella toista ID:tä, saa HTML ja JavaScript sopimaan yhteen.
AI-generoitu kuvitus vastaavasta id="root" mount-elementistä. Se on käsitteellinen koodieditorinäkymä, ei kuvakaappaus tietystä framework-mallista.
Vaihe 3: Käytä React 18:n root-API:a oikeassa järjestyksessä
React 18 esitteli createRoot-asiakaspuolen API:n. Virallinen React 18 -päivitysopas näyttää migraation vanhasta ReactDOM.render-kuviosta muotoon:
Yllättävän helppo virhe on sekoittaa DOM-kontainerin ja React-komponentin roolit:
// Wrong
createRoot(<App />);
React listaa tämän nimenomaisesti toiseksi yleiseksi syyksi virheeseen “Target container is not a DOM element”. createRoot() vastaanottaa DOM-solmun; root.render() vastaanottaa React-solmun.
Toinen migraatiovirhe on React 17:n allekirjoituksen säilyttäminen mielessä ja yritys välittää kontaineri funktiolle root.render():
React 18 -päivitysopas näyttää muodossa createRoot(container!) TypeScript-muodon. Huutomerkki on käännösaikainen väite: se kertoo TypeScriptille, että uskot arvon olevan ei-null. Se ei luo puuttuvaa HTML-elementtiä ajonaikana.
Turvallisempi kuvio debuggauksen aikana on:
const container = document.getElementById('root');
if (container === null) {
throw new Error('Expected #root to exist');
}
createRoot(container).render(<App />);
Tämä tuottaa hyödyllisemmän sovelluskohtaisen virheen, jos HTML ja JavaScript ajautuvat erilleen.
Soveltuu, kun: ongelma ilmestyi React 17 → React 18 -migraation aikana, kopioituasi sisääntulotiedoston toisesta projektista, tai vain TypeScript-käännöksissä, joihin lisättiin ! kääntäjän varoituksen hiljentämiseksi.
Toimenpide: varmista kutsujärjestys: DOM-haku → createRoot(container) → root.render(<App />). Debuggauksen aikana suosii eksplisiittistä null-tarkistusta sokean väitteen container! sijaan.
AI-generoitu kuvitus puolustavasta React 18:n käynnistyskuviosta. Koodi näytetään käsitteellisenä esimerkkinä, ei kaapattuna tulosteena todellisesta projektista.
Vaihe 4: Varmista, että käynnistyskoodisi suoritetaan kohde-elementin olemassaolon jälkeen
ID voi olla täydellisesti kirjoitettu ja silti palauttaa null, jos skriptisi suoritetaan ennen kuin selain on jäsennellyt elementin. Reactin vianmääritysdokumentit varoittavat nimenomaisesti, että bundle-skripti ei voi nähdä DOM-solmuja, jotka esiintyvät myöhemmin HTML:ssä, jos suoritus tapahtuu liian aikaisin.
Tämä on pääasiassa relevanttia mukautetuille HTML-sivuille ja vanhemmille upotusasetuksille. Yleinen turvallinen asettelu on laittaa mount-elementti ennen skriptiä:
Jos hallitset mukautettua skriptiä, joka voi suorittaa ennen jäsennyksen valmistumista, toinen puolustava vaihtoehto on odottaa DOMContentLoaded-tapahtumaa:
function start() {
const container = document.getElementById('root');
if (!container) throw new Error('Root element not found');
createRoot(container).render(<App />);
}
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', start);
} else {
start();
}
Älä lisää tätä wrapperia automaattisesti jokaiseen React-projektiin. Nykyaikaiset bundlerit ja frameworkit hallinnoivat yleensä sisääntuloskriptin sijoittelua ja lataussemantiikkaa puolestasi. Jos tavallinen Vite-, Next.js-, Remix- tai framework-generoitu sovellus kehittää äkillisesti tämän virheen, etsi ensin muutettua mallia, mount-ID:tä, mukautettua integraatiota tai koodia, joka suoritetaan odotetun selain-sisääntulopisteen ulkopuolella.
Soveltuu, kun: sama ID on olemassa lopullisessa HTML:ssä, mutta haku on edelleen null käynnistyksen aikana, erityisesti manuaalisesti koottu HTML-sivu, CMS-malli, widget-upotus tai kolmannen osapuolen skripti-integraatio.
Toimenpide: tutki todellista sivun lähdettä ja suoritusjärjestystä. Varmista, että mount-solmu on olemassa ennen koodia, joka kutsuu funktiota createRoot().
AI-generoitu kuvitus DOM-valmiusguardista mukautettua React-bootstrapia varten. Se ei ole vaadittu kuvio jokaiselle React 18 -sovellukselle; käytä sitä vain, kun käynnistysajoitus on todellinen ongelma.
Jos sivusi on palvelinrenderöity, käytä hydrateRootia sen sijaan
On olemassa tärkeä ehto, jossa kelvollinen DOM-elementti ei riitä tekemään createRoot():sta oikeaa API:a. Jos kontaineri sisältää jo HTML:tä, jonka React on generoinut palvelimella tai käännösaikana, Reactin dokumentaatio sanoo käyttäväsi hydrateRoot():ia createRoot():n sijaan.
import { hydrateRoot } from 'react-dom/client';
import App from './App';
const container = document.getElementById('root');
if (!container) {
throw new Error('Root element not found');
}
hydrateRoot(container, <App />);
Syy on erilainen kuin target-container-virhe. createRoot() hallinnoi asiakasrenderöityä juurta ja tyhjentää ensimmäisellä renderöinnillä olemassa olevan HTML:n juuren sisällä. hydrateRoot() liittää Reactin HTML:ään, jonka React on jo tuottanut palvelimella. Virallinen createRoot-dokumentaatio mainitsee tämän nimenomaisesti palvelinrenderöinnin ansana.
Soveltuu, kun: sinulla on palvelinrenderöityä React HTML:tä, staattinen generointi, joka emittoi React-merkintää, tai framework, joka hydraa HTML:n selaimessa.
Jos tämä on modaalin tai tooltipin kohde, saatat tarvita createPortal–ei toista juurta
Joissakin tapauksissa kehittäjät näkevät puuttuvan kontainerin yrittäessään renderöidä modaalin, tooltipin, toast-alueen tai peitteen pääsovelluspuun ulkopuolelle. Reactin dokumentit sanovat, että kun haluat JSX:n ilmestyvän muualle DOM:iin, käytä createPortal():ia luomatta toista juurta vain sitä lapsi UI:ta varten.
import { createPortal } from 'react-dom';
function Modal({ children }) {
const modalRoot = document.getElementById('modal-root');
if (!modalRoot) return null;
return createPortal(children, modalRoot);
}
Virallinen createPortal-dokumentaatio sanoo, että portaalin kohteen on oltava olemassa. Portaali voi siis tuottaa liittyvän kontaineriongelman, jos modal-root puuttuu, mutta arkkitehtoninen korjaus ei välttämättä ole “kutsu createRootia uudelleen”.
Soveltuu, kun: epäonnistuva kontaineri ei ole sovelluksesi pääjuuri vaan peitekohde tai solmu, jota hallinnoidaan komponentin normaalin DOM-sijainnin ulkopuolella.
Toimenpide: pidä yksi normaali sovellusjuuri, ellet todella tarvitse useita riippumattomia juuria. Modaalityyppiselle UI:lle samassa React-sovelluksessa suosii portaalia olemassa olevaan DOM-solmuun.
Mitä jos virhe tapahtuu vain testeissä?
Testi voi epäonnistua samasta perussyystä: odotettua kontaineria ei koskaan lisätty testin DOM:iin. Jos testisi kutsuu manuaalisesti createRoot(document.getElementById('root')), varmista, että testin asetukset todella luovat tuon solmun ennen renderöintiä.
Monet React-testauskirjastot hallinnoivat kontainereita puolestasi. Jos käytät jo testausframeworkin render()-apufunktiota, React-juuren manuaalinen luominen voi olla tarpeetonta ja tehdä testin asetuksista hauraampia.
Soveltuu, kun: kehitys toimii selaimessa, mutta Jest, Vitest, JSDOM tai toinen testiympäristö heittää kontainerivirheen.
Toimenpide: tutki testin DOM-asetuksia, älä tuotannon index.html:ää. Varmista, että solmu on olemassa ympäristössä, jossa epäonnistuva koodi todella suoritetaan.
Mitä jos document ei ole saatavilla?
Jos koodi, joka kutsuu document.getElementById():ia, suoritetaan palvelimella tai muussa ei-selainympäristössä, sinulla on erilainen integraatio-ongelma. Reactin asiakaspuolen API:t react-dom/client:ssä on suunniteltu renderöimään selain-DOM-solmuihin. Palvelinrenderöinti käyttää API:ita react-dom/server:stä, ja frameworkit erottavat yleensä palvelin- ja asiakassisääntulopisteet.
Soveltuu, kun: virhe ilmenee palvelinpuolen renderöinnin aikana, Node-käännösvaiheessa tai koodissa, joka on jaettu palvelin- ja selaimen bundlejen kesken.
Toimenpide: siirrä selainkohtainen juuren luonti asiakassisääntulopisteeseen. Jos käytät frameworkia, noudata sen dokumentoitua palvelin/asiakasrajaa sen sijaan, että kutsuisit manuaalisesti createRoot():ia jaetusta palvelinkoodista.
Nopea diagnoositaulukko
Mitä näet
Luultava syy
Paras seuraava tarkistus
console.log(container) on null
ID-epäsovuus tai elementti ei ole vielä läsnä
Vertaa HTML-ID:tä ja hakua; tutki skriptin ajoitusta
HTML käyttää id="app", koodi kysyy root
Mount-ID-epäsovuus
Tee molemmista nimistä identtiset
createRoot(<App />)
React-elementti välitetty, missä DOM-solmua vaaditaan
Välitä DOM-solmu createRoot:lle, sitten renderöi <App />
Projekti käyttää edelleen ReactDOM.render:iä React 18 -päivityksen jälkeen
Legacy-asiakas-API
Migroi createRoot:iin käyttäen React 18 -päivitysopasta
Kontaineri sisältää jo palvelinrenderöityä React HTML:tä
Väärä asiakasalustus-API
Käytä hydrateRoot:ia
Vain modaali/tooltip-kohde epäonnistuu
Puuttuva portaalikohde tai tarpeeton ylimääräinen juuri
Käytä createPortal:ia olemassa olevan DOM-solmun kanssa
Vain testit epäonnistuvat
Testin DOM ei koskaan luonut kohde-elementtiä
Luo kontaineri testin asetuksissa tai käytä testikirjaston renderöijää
Lopullinen varmistus: vahvista korjaus virheen piilottamisen sijaan
Tehdyssä muutoksen jälkeen varmista käynnistyspolku tässä järjestyksessä:
Avaa sivu ja tutki selainkonsolia. Target-container-virheen tulisi olla poissa.
Suorita console.log(document.getElementById('root')) ja varmista, että se tulostaa todellisen elementin, ei null.
Varmista, että importoit createRoot:in react-dom/client:stä React 18 -asiakasrenderöidyssä sovelluksessa.
Varmista, että DOM-elementti välitetään createRoot():lle ja React-komponentti välitetään root.render():lle.
Jos sivu renderöitiin Reactilla palvelimella, varmista, että asiakas käyttää hydrateRoot():ia sen sijaan.
Jos epäonnistuva kohde on modaali tai tooltip, varmista, että portaalikohde on olemassa ennen createPortal():n kutsumista.
Älä pidä TypeScriptin ei-null-väitettä, valinnaisketjua tai catch-lohkosta korjauksena itsessään. Nämä tekniikat voivat hiljentää virhepolun toimittamatta DOM-solmua, jota React todella tarvitsee. Kestävä korjaus on saada sivurakenne, alustus-API ja suoritusajoitus sopimaan yhteen.
Normaalissa React 18 -yksisivusovelluksessa lyhyin oikea henkinen malli on: HTML luo kontainerin; JavaScript löytää tuon kontainerin; createRoot ottaa kontainerin; root.render ottaa komponentin. Kun nämä neljä palaa ovat oikeassa järjestyksessä, “Target container is not a DOM element” katoaa yleensä oikeasta syystä.