Heim
» Grundvallarþekking
»
Hvernig á að laga villuna „Target container is not a DOM element“ í React 18
Hvernig á að laga villuna „Target container is not a DOM element“ í React 18
Algengasta lausnin er þessi: vertu viss um að gildið sem þú sendir í createRoot() sé raunveruleg DOM-nóð sem er þegar til staðar. Í React 18 lítur venjulegur viðskiptavinur (client) inngangspunktur svona út:
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 />);
Ef document.getElementById('root') skilar null, eða ef þú kemur óvart React-staki eins og <App /> í createRoot(), getur React ekki búið til rót og getur tilkynnt „Target container is not a DOM element.“ Eigin leiðbeiningar React um að leysa createRoot vandamál skilgreina villuna nákvæmlega á þennan hátt: gildið sem sent er í createRoot er ekki DOM-nóð.
Þessi leiðbeining byrjar á þessum líklegasta orsök, fjallar síðan um tímasetningarvandamál, villur við uppfærslu í React 18, þjónasíðugerð (server rendering), portala, TypeScript og prófunarumhverfi svo þú getir stöðvað leitina þegar þú finnur tilvikið sem passar við forritið þitt.
Skref 1: Sannaðu hvað þú ert í raun að senda í createRoot()
Áður en þú breytir stillingum, skráðu innihaldshólinn (container) í skilagreinar:
Ef skilagreinin prentar null, er React ekki hlutinn sem bilaði fyrst. Vafarinn fann ekki stak með þessu ID á þeim tíma sem kóðinn keyrði. Opinber leiðbeiningar React um að leysa vandamál nefna ID-ósamræmi og keyrslu áður en DOM-nóðin er til sem algengar ástæður.
Ef skilagreinin prentar eitthvað eins og <div id="root"></div>, þá er innihaldshóllinn til staðar og þú ættir að hoppa yfir í React API, SSR, portal eða umhverfisathuganir hér að neðan.
Á við þegar: villan kemur strax við ræsingu forritsins, sérstaklega í main.jsx, index.jsx eða index.tsx.
Aðgerð: giskaðu ekki. Skráðu nákvæmlega hvaða gildi er sent í createRoot(). Ef það er null, lagaðu ástæðuna fyrir að DOM-leitin mistókst áður en þú snertir kóða íhluta (components).
AI-búin til mynd af React 18 innihaldshólsvillunni í þróunarskilagreini. Þetta er ekki skjámynd úr raunverulegu forriti eða React DevTools.
Skref 2: Passaðu að HTML ID passi við JavaScript-leitina
Einfaldasta raunverulega orsökin er ósamræmi milli HTML og JavaScript.
HTML-ið þitt gæti innihaldið:
<div id="app"></div>
en React inngangsskráin þín leitar að:
document.getElementById('root')
Nöfnin verða að passa. Annaðhvort breyttu merkingunni (markup):
<div id="root"></div>
eða breyttu leitinni:
const container = document.getElementById('app');
Núverandi createRoot tilvísun React notar staðlaða dæmið document.getElementById('root'), en root er ekki töfrandi nauðsynlegt ID. Hvert raunverulegt DOM-stak má nota sem rót-innihaldshól. Mikilvæga skilyrðið er að stakið sé til staðar og að leitinni skili því.
Á við þegar: þú breyttir nýlega HTML sniðmáti, fluttir frá Create React App yfir í Vite eða annan pakka (bundler), innfelldir React í núverandi þjónasíðugerða síðu, eða endurnefndir festingarstakið (mount element).
Aðgerð: leitaðu í verkefninu að bæði id="root" og getElementById('root'). Ef verkefnið notar viljandi annað ID, láttu HTML og JavaScript samræmast.
AI-búin til mynd af samsvarandi id="root" festingarstaki. Þetta er huglægt kóðaritla-sýn, ekki skjámynd af ákveðnu rammaverkasniðmáti.
Skref 3: Notaðu React 18 rót-API-ið í réttri röð
React 18 kynnti createRoot viðskiptavina-API-ið. Opinbera React 18 uppfærsluleiðbeiningin sýnir flutning frá eldri ReactDOM.render mynstrinu yfir í:
Ótrúlega auðveld villa er að víxla hlutverkum DOM-innihaldshólsins og React-íhlutarins:
// Rangt
createRoot(<App />);
React nefnir þetta sérstaklega sem aðra algenga orsök „Target container is not a DOM element“ villunnar. createRoot() tekur við DOM-nóðinni; root.render() tekur við React-nóðinni.
Önnur flutningsvilla er að halda í React 17 undirskriftina í huganum og reyna að senda innihaldshólinn í root.render():
createRoot tilvísun React skjalfestir root.render(reactNode) sem tekur við React-nóðinni, en innihaldshóllinn tilheyrir createRoot(domNode).
TypeScript: blandu ekki saman non-null fullyrðingu og keyrslulausn
React 18 uppfærsluleiðbeiningin sýnir createRoot(container!) sem TypeScript form. Upphrópunin er fullyrðing við þýðingu (compile-time): hún segir TypeScript að þú trúir að gildið sé ekki null. Hún býr ekki til vantarandi HTML-stak við keyrslu.
Öruggara mynstur þegar þú ert að villuleita er:
const container = document.getElementById('root');
if (container === null) {
throw new Error('Expected #root to exist');
}
createRoot(container).render(<App />);
Þetta gefur gagnlegri forritssérhæfða villu ef HTML og JavaScript fara í sundur.
Á við þegar: vandamálið kom upp við React 17 → React 18 uppfærslu, eftir að hafa afritað inngangsskrá frá öðru verkefni, eða aðeins í TypeScript byggingum þar sem ! var bætt við til að þagga niður í þýðaravörun.
Aðgerð: staðfestu keyrsluröðina: DOM leit → createRoot(container) → root.render(<App />). Við villuleit, kýssu skýra null-athugun fram yfir að fullyrða blindlega container!.
AI-búin til mynd af varnandi React 18 ræsingarmynstri. Kóðinn er sýndur sem huglægt dæmi, ekki sem fengið úttak úr raunverulegu verkefni.
Skref 4: Passaðu að ræsingarkóðinn keyri eftir að markstakið er til staðar
ID getur verið rétt stafsett og samt skilað null ef skriftið þitt keyrir áður en vafarinn hefur túlkað stakið. Leiðbeiningar React um að leysa vandamál vara sérstaklega við að pakkað skrift geti ekki séð DOM-nóðir sem koma síðar í HTML-ið ef keyrslan á sér stað of snemma.
Þetta er aðallega viðeigandi fyrir sérsniðnar HTML síður og eldri innfellingaruppsetningar. Algengt öruggt uppsetning er að setja festingarstakið á undan skriftinu:
Ef þú stjórnar sérsniðnu skrifti sem getur keyrt áður en túlkun er lokið, er annað varnandi valkostur að bíða eftir DOMContentLoaded:
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();
}
Bættu ekki þessari umgjörð sjálfkrafa við hvert React verkefni. Nútíma pakkari og rammaverkjastýringar stjórna venjulega staðsetningu inngangsskrifta og hleðsluhegðun fyrir þig. Ef staðlað Vite, Next.js, Remix eða rammaverkagert forrit þróar skyndilega þessa villu, leitaðu fyrst að breyttu sniðmáti, festingar ID, sérsniðinni samþættingu eða kóða sem keyrir utan vænlegs vafarainngangspunkts.
Á við þegar: sama ID er til staðar í lok HTML-ið en leitinni skilar samt null við ræsingu, sérstaklega í handsmíðaðri HTML síðu, CMS sniðmáti, widget innfellingu eða þriðja aðila skriftasamþættingu.
Aðgerð: skoðaðu raunverulega síðugrunninn og keyrsluröðina. Passaðu að festingar-nóðin sé til staðar áður en kóðinn sem kallar á createRoot() keyrir.
AI-búin til mynd af DOM-tilbúinnisvörn fyrir sérsniðna React ræsingu. Þetta er ekki nauðsynlegt mynstur fyrir hvert React 18 forrit; notaðu það aðeins ef ræsingartímasetning er í raun vandamálið.
Ef síðan þín er þjónasíðugerð, notaðu hydrateRoot í staðinn
Það er mikilvægt skilyrði þar sem gild DOM-nóð er ekki nægjanlegt til að gera createRoot() að rétta API-ið. Ef innihaldshóllinn inniheldur þegar HTML sem React bjó til á þjóninum eða við byggingu, segir skjölun React að nota hydrateRoot() í stað createRoot().
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 />);
Ástæðan er önnur en target-container villan. createRoot() stjórnar viðskiptavinasíðugerðri rót og hreinsar til staðar HTML inni í þeirri rót við fyrstu teikningu. hydrateRoot() tengir React við HTML sem var þegar framleitt af React á þjóninum. Opinbera createRoot skjölunin nefnir þetta sérstaklega sem þjónasíðugerðar gildru.
Á við þegar: þú ert með þjónasíðugerð React HTML, stöðuga síðugerð (static generation) sem gefur frá sér React merkingu, eða rammaverki sem hydratunar HTML í vafranum.
Aðgerð: „lagaðu“ ekki SSR með því að skipta út þjónamerkingu fyrir tóman innihaldshól. Notaðu hydratunarinngangspunkt rammaverksins eða hydrateRoot() React eftir því sem við á.
Ef þetta er modal eða tooltip markmið, gætirðu þurft createPortal – ekki aðra rót
Stundum sjá þróunaraðilar vandan innihaldshól þegar þeir reyna að teikna modal, tooltip, toast svæði eða yfirlag (overlay) utan við megin forritatræðina. Skjölun React segir að þegar þú vilt að JSX birtist annars staðar í DOM-ið, notaðu createPortal() frekar en að búa til aðra rót bara fyrir þann undir-UI.
import { createPortal } from 'react-dom';
function Modal({ children }) {
const modalRoot = document.getElementById('modal-root');
if (!modalRoot) return null;
return createPortal(children, modalRoot);
}
Opinbera createPortal skjölunin segir að portal markmiðið verði að vera til staðar. Þannig geta portala valdið skyldum flokki innihaldshólsvandamála ef modal-root vantar, en arkitektúrlausnin er ekki endilega „kalla á createRoot aftur.“
Á við þegar: bilandi innihaldshóllinn er ekki megin rót forritsins þíns, heldur yfirlagsáfangastaður eða nóð sem stjórnað er utan við venjulega DOM-staðsetningu íhlutarins.
Aðgerð: haltu einni venjulegri forritsrót nema þú þurfir virkilega margar óháðar rætur. Fyrir modal-stíla UI innan sama React forrits, kýssu portal í núverandi DOM-nóð.
Hvað ef villan kemur aðeins fram í prófunum?
Prófun getur mistekist af sömu grundvallarástæðu: væntanlegur innihaldshóll var aldrei settur inn í prófunar-DOM-ið. Ef prófunin þín kallar handvirkt á createRoot(document.getElementById('root')), passaðu að prófunaruppsetningin búi virkilega til þá nóð áður en teiknað er.
Hins vegar stjórna mörg React prófunarhöfn innihaldshólum fyrir þig. Ef þú ert nú þegar að nota render() hjálparfall prófunarrammaverks, getur handvirk gerð React rót verið óþörf og gert prófunaruppsetninguna viðkvæmari.
Á við þegar: þróun virkar í vafranum en Jest, Vitest, JSDOM eða annað prófunarumhverfi kastar innihaldshólsvillunni.
Aðgerð: skoðaðu DOM-uppsetningu prófunarinnar, ekki framleiðslu index.html. Staðfestu að nóðin sé til staðar inni í umhverfinu þar sem bilandi kóðinn keyrir í raun.
Hvað ef document er ekki í boði?
Ef kóði sem kallar á document.getElementById() keyrir á þjóni eða öðru umhverfi sem er ekki vafi, ertu með annað samþættingarvandamál. Viðskiptavina-API-ið React í react-dom/client er hannað til að teikna inn í vafra DOM-nóðir. Þjónasíðugerð notar API-ið frá react-dom/server, og rammaverkjastýringar aðskilja venjulega þjóna- og viðskiptavina inngangspunkta.
Á við þegar: villan kemur fram við þjónasíðugerð, Node byggingarskref, eða kóða sem er deilt á milli þjóna- og vafrapakka.
Aðgerð: færið aðeins-vafra rótargerð inn í viðskiptavina inngangspunktinn. Ef þú notar rammaverki, fylgdu skjalfestum þjóna/viðskiptavina mörkum þess frekar en að kalla handvirkt á createRoot() úr deildum þjónakóða.
Hraðgreiningartafla
Hvað þú sérð
Líkleg orsök
Besta næsta athugun
console.log(container) er null
ID ósamræmi eða stak ekki til staðar ennþá
Berið saman HTML ID og leit; skoðið skriftatímasetningu
HTML notar id="app", kóði leitar að root
Festingar ID ósamræmi
Láttu bæði nöfnin vera eins
createRoot(<App />)
React stak sent þar sem DOM nóð er krafist
Sendu DOM nóðina í createRoot, teiknaðu síðan <App />
Verkefni notar enn ReactDOM.render eftir React 18 uppfærslu
Eldri viðskiptavina API
Fluttu yfir í createRoot með React 18 uppfærsluleiðbeiningunni
Innihaldshóll inniheldur þegar þjónasíðugerð React HTML
Rangt viðskiptavina frumstillingar API
Notaðu hydrateRoot
Aðeins modal/tooltip markmið bilast
Vand portal markmið eða óþarfa aukarót
Notaðu createPortal með núverandi DOM nóð
Aðeins prófanir mistekjast
Prófunar DOM bjó aldrei til markstakið
Búðu til innihaldshólinn í prófunaruppsetningu eða notaðu teiknara prófunarhöfnarinnar
Loka staðfesting: staðfestu lagfæringuna í stað þess að fela villuna
Eftir að hafa gert breytingu, staðfestu ræsingarleiðina í þessari röð:
Opnaðu síðuna og skoðaðu vafra skilagreina. Target-container villan ætti að vera horfin.
Keyrðu console.log(document.getElementById('root')) og staðfestu að hún prenti raunverulegt stak, ekki null.
Staðfestu að þú flytur inn createRoot frá react-dom/client í React 18 viðskiptavinasíðugerðu forriti.
Staðfestu að DOM stakið sé sent í createRoot() og React íhluturinn sé sendur í root.render().
Ef síðan var teiknuð af React á þjóninum, staðfestu að viðskiptavinurinn noti hydrateRoot() í staðinn.
Ef bilandi áfangastaðurinn er modal eða tooltip, staðfestu að portal markmiðið sé til staðar áður en createPortal() er kallað á.
Lít ekki á TypeScript non-null fullyrðingu, valkvæða keðju (optional chaining) eða catch blokk sem lausnina í sjálfu sér. Þessar aðferðir geta þaggað niður í villu leið án þess að veita DOM nóðina sem React þarf í raun. Varanlega lausnin er að láta síðusturð, frumstillingar API og keyrslutímasetningu samræmast.
Fyrir venjulegt React 18 einnar síðu forrit (SPA), er stysta rétta huglæga líkanið: HTML-ið býr til innihaldshól; JavaScript finnur þann innihaldshól; createRoot tekur við innihaldshólinum; root.render tekur við íhlutnum. Þegar þessir fjórir hlutar eru í réttri röð, hverfur „Target container is not a DOM element“ venjulega af rétta ástæðu.