Sådan løser du fejlen 'Target container is not a DOM element' i React 18

Den vigtigste løsning er denne: Sørg for, at den værdi, du sender til createRoot(), er et faktisk DOM-element, der allerede eksisterer. I React 18 ser det normale klient-startpunkt sådan ud:

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 />);

Hvis document.getElementById('root') returnerer null, eller hvis du ved en fejl sender et React-element som <App /> til createRoot(), kan React ikke oprette en rod og rapportere fejlen “Target container is not a DOM element.” Reacts egen fejlfinding-dokumentation for createRoot definerer fejlen præcis på denne måde: Værdien, der sendes til createRoot, er ikke et DOM-node.

Denne guide starter med den mest sandsynlige årsag og dækker derefter timing-problemer, migreringsfejl fra React 18, server-rendering, portals, TypeScript og testmiljøer, så du kan stoppe, når du finder den sag, der matcher din app.

Trin 1: Bevis hvad du faktisk sender til createRoot()

Før du ændrer konfigurationen, skal du logge containeren:

const container = document.getElementById('root');
console.log(container);

const root = createRoot(container);

Hvis konsollen udskriver null, er det ikke React, der fejlede først. Browseren fandt ikke et element med det ID på det tidspunkt, din kode kørte. Reacts officielle fejlfindingsafsnit nævner et ID-mismatch og eksekvering før DOM-noden eksisterer som almindelige årsager.

Hvis konsollen udskriver noget i stil med <div id="root"></div>, så eksisterer containeren, og du skal springe videre til React API-, SSR-, portal- eller miljøkontrollerne nedenfor.

Gælder når: Fejlen opstår øjeblikkeligt under opstart af applikationen, især i main.jsx, index.jsx eller index.tsx.

Handling: Gæt ikke. Log den præcise værdi, der sendes til createRoot(). Hvis den er null, skal du løse årsagen til, at DOM-opslaget fejlede, før du rører komponentkoden.

AI-genereret illustration af kodeeditor, der viser React-fejlen Target container is not a DOM element
AI-genereret illustration af React 18-containerfejlen i en udviklerkonsol. Det er ikke et skærmbillede fra en rigtig applikation eller React DevTools.

Trin 2: Få HTML-ID'et til at matche JavaScript-opslaget

Den simpleste årsag i den virkelige verden er et mismatch mellem din HTML og din JavaScript.

Din HTML kan indeholde:

<div id="app"></div>

Mens din React-entry-fil spørger efter:

document.getElementById('root')

Disse navne skal matche. Enten ændrer du markuppen:

<div id="root"></div>

Eller ændrer du opslaget:

const container = document.getElementById('app');

Reacts nuværende createRoot-reference bruger standardeksemplet document.getElementById('root'), men root er ikke et magisk påkrævet ID. Ethvert rigtigt DOM-element kan bruges som rod-container. Den vigtige betingelse er, at elementet eksisterer, og at opslaget returnerer det.

Gælder når: Du har for nylig ændret en HTML-skabelon, migreret fra Create React App til Vite eller en anden bundler, indlejret React i en eksisterende server-renderet side, eller omdøbt mount-elementet.

Handling: Søg i projektet efter både id="root" og getElementById('root'). Hvis projektet bevidst bruger et andet ID, skal du få HTML og JavaScript til at være enige.

AI-genereret illustration af kodeeditor, der fremhæver en div med id root i en HTML-fil
AI-genereret illustration af et matchende id="root" mount-element. Det er en konceptuel kodeeditor-visning, ikke et skærmbillede af en bestemt frameworks-skabelon.

Trin 3: Brug React 18 rod-API'en i den korrekte rækkefølge

React 18 introducerede klient-API'en createRoot. Den officielle React 18 opgraderingsguide viser migreringen fra det ældre ReactDOM.render-mønster til:

import { createRoot } from 'react-dom/client';

const container = document.getElementById('root');
const root = createRoot(container);
root.render(<App />);

En overraskende let fejl er at bytte om på DOM-containeren og React-komponenten:

// Forkert
createRoot(<App />);

React nævner eksplicit dette som en anden almindelig årsag til fejlen “Target container is not a DOM element”. createRoot() modtager DOM-noden; root.render() modtager React-noden.

En anden migreringsfejl er at tage React 17-signaturen med mentalt og forsøge at sende containeren til root.render():

// Forkert mental model
root.render(<App />, container);

// Korrekt
const root = createRoot(container);
root.render(<App />);

Reacts createRoot-reference dokumenterer root.render(reactNode) som tagende React-noden, mens containeren hører til createRoot(domNode).

TypeScript: Forveksl ikke non-null assertion med en runtime-løsning

React 18 opgraderingsguiden viser createRoot(container!) som en TypeScript-form. Udråbstegnet er en compile-time assertion: Det fortæller TypeScript, at du tror, værdien ikke er null. Det opretter ikke et manglende HTML-element ved runtime.

Et sikrere mønster, når du debugger, er:

const container = document.getElementById('root');

if (container === null) {
  throw new Error('Expected #root to exist');
}

createRoot(container).render(<App />);

Dette producerer en mere nyttig applikationsspecifik fejl, hvis HTML og JavaScript driver fra hinanden.

Gælder når: Problemet opstod under en migrering fra React 17 → React 18, efter at have kopieret en entry-fil fra et andet projekt, eller kun i TypeScript-builds, hvor ! blev tilføjet for at dæmpe en compiler-advarsel.

Handling: Verificer kaldsekvensen: DOM lookup → createRoot(container) → root.render(<App />). Foretræk en eksplicit null-check frem for blindt at assertere container! under debugging.

AI-genereret illustration af kodeeditor, der viser en null-check før createRoot og root render i React 18
AI-genereret illustration af et defensivt React 18 opstartsmønster. Koden vises som et konceptuelt eksempel, ikke som fanget output fra et faktisk projekt.

Trin 4: Sørg for, at din opstartskode kører, efter at målelementet eksisterer

Et ID kan være perfekt stavet og stadig returnere null, hvis dit script kører, før browseren har parset elementet. Reacts fejlfindingsdokumentation advarer specifikt om, at et bundle-script ikke kan se DOM-noder, der dukker op senere i HTML'en, hvis eksekveringen sker for tidligt.

Dette er primært relevant for brugerdefinerede HTML-sider og ældre indlejringssætups. Et almindeligt sikkert layout er at placere mount-elementet før scriptet:

<body>
  <div id="root"></div>
  <script type="module" src="/src/main.jsx"></script>
</body>

Hvis du styrer et brugerdefineret script, der kan køre, før parsing er færdig, er en anden defensiv mulighed at vente på 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();
}

Tilføj ikke denne wrapper automatisk til alle React-projekter. Moderne bundlers og frameworks håndterer typisk placering og indlæsningssemantik for entry-scripts for dig. Hvis en standard Vite, Next.js, Remix eller framework-genereret app pludselig udvikler denne fejl, skal du først kigge efter en ændret skabelon, mount-ID, brugerdefineret integration eller kode, der kører uden for det forventede browser-startpunkt.

Gælder når: Det samme ID eksisterer i den endelige HTML, men opslaget er stadig null under opstart, især i en manuelt samlet HTML-side, CMS-skabelon, widget-indlejring eller tredjeparts-script-integration.

Handling: Inspectér den faktiske sidekilde og eksekveringsrækkefølgen. Sørg for, at mount-noden eksisterer, før koden, der kalder createRoot().

AI-genereret illustration af kodeeditor, der viser en DOMContentLoaded-guard før oprettelse af en React rod
AI-genereret illustration af en DOM-readiness-guard for en brugerdefineret React bootstrap. Det er ikke et påkrævet mønster for alle React 18 apps; brug det kun, når opstartstiming faktisk er problemet.

Hvis din side er server-renderet, skal du bruge hydrateRoot i stedet

Der er en vigtig betingelse, hvor et gyldigt DOM-element ikke er nok til at gøre createRoot() til den korrekte API. Hvis containeren allerede indeholder HTML genereret af React på serveren eller ved build-tid, siger Reacts dokumentation, at du skal bruge hydrateRoot() i stedet for 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 />);

Årsagen er forskellig fra target-container-fejlen. createRoot() administrerer en klient-renderet rod og rydder eksisterende HTML inde i den rod ved den første render. hydrateRoot() tilknytter React til HTML, der allerede er produceret af React på serveren. Den officielle createRoot-dokumentation fremhæver dette eksplicit som en server-rendering faldgrube.

Gælder når: Du har server-renderet React HTML, statisk generering, der udsender React markup, eller et framework, der hydrerer HTML i browseren.

Handling: “Fix” ikke SSR ved at erstatte server markup med en tom container. Brug frameworkets hydrerings-entry-punkt eller Reacts hydrateRoot() som passende.

Hvis dette er en modal eller tooltip-mål, har du måske brug for createPortal – ikke en anden rod

Nogle gange ser udviklere en manglende container, mens de forsøger at render en modal, tooltip, toast-region eller overlay uden for det primære app-træ. Reacts docs siger, at når du vil have JSX til at dukke op et andet sted i DOM'en, skal du bruge createPortal() frem for at oprette en anden rod kun for den børne-UI.

import { createPortal } from 'react-dom';

function Modal({ children }) {
  const modalRoot = document.getElementById('modal-root');

  if (!modalRoot) return null;

  return createPortal(children, modalRoot);
}

Den officielle createPortal-dokumentation siger, at portal-målet allerede skal eksistere. Så portals kan producere en relateret klasse af container-problemer, hvis modal-root mangler, men den arkitektoniske løsning er ikke nødvendigvis “kald createRoot igen”.

Gælder når: Den fejlede container er ikke din applikations primære rod, men en overlay-destination eller en node administreret uden for komponentens normale DOM-position.

Handling: Behold én normal applikationsrod, medmindre du virkelig har brug for flere uafhængige rødder. For modal-stil UI inden for den samme React-applikation, foretræk en portal til et eksisterende DOM-node.

Hvad nu, hvis fejlen kun sker i tests?

En test kan fejle af samme fundamentale årsag: Den forventede container blev aldrig indsat i test-DOM'en. Hvis din test manuelt kalder createRoot(document.getElementById('root')), skal du sikre dig, at testopsætningen faktisk opretter den node før rendering.

beforeEach(() => {
  document.body.innerHTML = '<div id="root"></div>';
});

Men mange React-testbiblioteker administrerer containere for dig. Hvis du allerede bruger et testframeworks render()-helper, kan manuel oprettelse af en React rod være unødvendig og gøre testopsætningen mere skrøbelig.

Gælder når: Udvikling virker i browseren, men Jest, Vitest, JSDOM eller et andet testmiljø kaster container-fejlen.

Handling: Inspectér testens DOM-opsætning, ikke den produktions index.html. Bekræft, at noden eksisterer inde i det miljø, hvor den fejlede kode faktisk kører.

Hvad nu, hvis document ikke er tilgængeligt?

Hvis kode, der kalder document.getElementById(), eksekverer i en server eller andet ikke-browser miljø, har du et andet integrationsproblem. Reacts klient-API'er i react-dom/client er designet til at render ind i browser DOM-noder. Server-rendering bruger API'er fra react-dom/server, og frameworks adskiller normalt server- og klient-entry-points.

Gælder når: Fejlen opstår under server-side rendering, et Node build-trin eller kode delt mellem server- og browser-bundles.

Handling: Flyt browser-kun rod-oprettelse ind i klient-entry-pointet. Hvis du bruger et framework, skal du følge dets dokumenterede klient/server-grænse frem for manuelt at kalde createRoot() fra delt serverkode.

Hurtig diagnose-tabel

Hvad du serSandsynlig årsagBedste næste kontrol
console.log(container) er nullID-mismatch eller element ikke til stede endnuSammenlign HTML-ID og opslag; inspectér script-timing
HTML bruger id="app", kode spørger efter rootMount ID-mismatchGør begge navne identiske
createRoot(<App />)React-element sendt hvor DOM-node krævesSend DOM-noden til createRoot, render derefter <App />
Projektet bruger stadig ReactDOM.render efter en React 18 opgraderingLegacy klient-APIMigrér til createRoot ved hjælp af React 18 opgraderingsguiden
Containeren indeholder allerede server-renderet React HTMLForkert klient-initialiserings-APIBrug hydrateRoot
Kun en modal/tooltip-mål fejlerManglende portal-mål eller unødvendig ekstra rodBrug createPortal med et eksisterende DOM-node
Kun tests fejlerTest-DOM oprettede aldrig målelementetOpret containeren i testopsætningen eller brug testbibliotekets renderer

Endelig verifikation: Bekræft løsningen i stedet for at skjule fejlen

Efter at have foretaget en ændring, skal du verificere opstartsstien i denne rækkefølge:

  1. Åbn siden og inspectér browserkonsollen. Target-container-fejlen skal være væk.
  2. Kør console.log(document.getElementById('root')) og bekræft, at den udskriver et rigtigt element, ikke null.
  3. Bekræft, at du importerer createRoot fra react-dom/client i en React 18 klient-renderet app.
  4. Bekræft, at DOM-elementet sendes til createRoot() og React-komponenten sendes til root.render().
  5. Hvis siden blev renderet af React på serveren, skal du bekræfte, at klienten bruger hydrateRoot() i stedet.
  6. Hvis den fejlede destination er en modal eller tooltip, skal du bekræfte, at portal-målet eksisterer, før du kalder createPortal().

Overvej ikke en TypeScript non-null assertion, optional chaining eller en catch-blok som løsningen i sig selv. Disse teknikker kan dæmpe en fejlvej uden at levere det DOM-node, React faktisk har brug for. Den holdbare løsning er at få sidestrukturen, initialiserings-API'en og eksekveringstimen til at være enige.

For en normal React 18 single-page-applikation er den korteste korrekte mentale model: HTML'en opretter containeren; JavaScript finder den container; createRoot tager containeren; root.render tager komponenten. Når disse fire dele er i den rigtige rækkefølge, forsvinder “Target container is not a DOM element” normalt af den rigtige årsag.

Efterlad en kommentar

Sådan rettes "ENOSPC: Systemgrænse for filovervågning nået" i Linux

Sådan rettes "ENOSPC: Systemgrænse for filovervågning nået" i Linux

Ret fejl i Linux ENOSPC-filovervågning ved at kontrollere inotify-grænser, finde processer med mange overvågningsbehov, hæve grænser sikkert og gøre ændringer permanente.

Sådan rettes "Tailwind CSS-stilarter opdateres ikke" i en Vite React-app

Sådan rettes "Tailwind CSS-stilarter opdateres ikke" i en Vite React-app

Ret problemer med Tailwind CSS-stilarter, der ikke opdateres i Vite React, ved at kontrollere Tailwind v4-opsætning, CSS-import, kildekodedetektion, dynamiske klasser, HMR og forældede cacher.

Sådan rettes ModuleNotFoundError: Intet modul med navnet 'pip' i Python 3

Sådan rettes ModuleNotFoundError: Intet modul med navnet 'pip' i Python 3

Ret Python 3's ModuleNotFoundError for pip på Windows, macOS og Linux med ensurepip, OS-pakker, virtuelle miljøer og fortolkertjek.

Sådan rettes "Tilladelse nægtet (offentlig nøgle)" i GitHub SSH

Sådan rettes "Tilladelse nægtet (offentlig nøgle)" i GitHub SSH

Ret GitHub SSH-tilladelse nægtet (publickey) ved at kontrollere værten, den aktive SSH-nøgle, GitHub-kontoen, SSO-godkendelsen, den eksterne URL og port 22-adgang.

How to Fix “Git Push Rejected: Non-Fast-Forward” Without Losing Changes

How to Fix “Git Push Rejected: Non-Fast-Forward” Without Losing Changes

Fix a Git non-fast-forward push safely. Protect local work, fetch remote commits, choose merge or rebase, resolve conflicts, and push without losing changes.

Sådan rettes "Nginx 502 Bad Gateway" ved proxy til Node.js

Sådan rettes "Nginx 502 Bad Gateway" ved proxy til Node.js

Ret Nginx 502 Bad Gateway-fejl med en Node.js upstream ved at kontrollere app-porten, NGINX-logfiler, proxy_pass-adresse, containernetværk, timeouts og genindlæsning.

Sådan rettes "Type 'null' kan ikke tildeles til type" i TypeScript

Sådan rettes "Type 'null' kan ikke tildeles til type" i TypeScript

Retter TypeScripts fejl "Type 'null' kan ikke tildeles til type" med foreningstyper, indsnævring, standardværdier og sikre påstande under strictNullChecks.

Sådan retter du fejlen "Prisma Client Has Not Been Generated Yet"

Sådan retter du fejlen "Prisma Client Has Not Been Generated Yet"

Ret fejlen med Prisma Client, der ikke er genereret, ved at kontrollere din generator, schema, output-sti, imports, versioner, monorepo-opsætning og build-trin til deployment.

Sådan rettes "ERR_MODULE_NOT_FOUND" i Node.js ESM-importer

Sådan rettes "ERR_MODULE_NOT_FOUND" i Node.js ESM-importer

Ret Node.js ERR_MODULE_NOT_FOUND i ESM ved at kontrollere importstier, filtypenavne, pakkeinstallation, eksport, ESM-tilstand og rene installationer.

Sådan løser du SSL-certifikatproblemet: Unable to get local issuer certificate i Git

Sådan løser du SSL-certifikatproblemet: Unable to get local issuer certificate i Git

Løs Git-fejlen 'unable to get local issuer certificate' ved at identificere tillidsbackenden, installere den korrekte CA-kæde og holde SSL-verifikation aktiveret.