The ReactDOM.render method is deprecated in React 18 and will no longer be supported.
This means your React application is trying to use an old API to mount your root component, and React 18 is telling you it doesn’t know how to handle that request anymore. The system level failure is that the React DOM renderer, which is responsible for taking your React components and turning them into actual DOM elements that the browser can display, has been updated to expect a new way of being initialized. It’s essentially a version mismatch at the core of how React talks to your webpage.
Here are the common causes and their fixes:
1. Outdated react-dom Version
- Diagnosis: Check your
package.jsonfile. You should havereactandreact-domlisted as dependencies, and ideally, both should be at version 18.x. Ifreact-domis still on a version below 18, this is your problem. - Fix:
This command will updatenpm install react-dom@latest # or yarn add react-dom@latestreact-domto the latest compatible version with yourreactpackage, which should be 18.x if yourreactis also up-to-date. - Why it works: React 18 introduced the new concurrent rendering features, and the
createRootAPI is integral to enabling them. Older versions ofreact-domsimply don’t contain the necessary logic to work with React 18’s rendering engine.
2. Incorrect Root Mounting Code
- Diagnosis: Examine your
index.js(or equivalent entry file). Look for any code that usesReactDOM.render. It will likely look something like this:import ReactDOM from 'react-dom'; import App from './App'; ReactDOM.render(<App />, document.getElementById('root')); - Fix: Replace
ReactDOM.renderwith the newcreateRootAPI.
This change is fundamental. You now first get a reference to the DOM element you want to mount to, then you create a "root" instance from that element usingimport ReactDOM from 'react-dom/client'; // Note the '/client' import App from './App'; const container = document.getElementById('root'); const root = ReactDOM.createRoot(container); // Create a root root.render(<App />); // Render your appReactDOM.createRoot(), and finally, you callrender()on that root instance. - Why it works:
createRootis React 18’s new entry point for the DOM. It sets up the environment for concurrent rendering and tells React where in the DOM your application lives.ReactDOM.renderwas the old way and is no longer part of the public API for React 18.
3. Multiple React Installations (Less Common)
- Diagnosis: If you’re working on a large project or have integrated React into an existing non-React application, you might accidentally have multiple versions of React or
react-dominstalled, or they might be resolved incorrectly. Runnpm ls react-domoryarn list react-domin your project’s root directory. If you see multiple versions listed or unexpected entries, this could be the culprit. - Fix: Clean your
node_modulesand reinstall:
If the problem persists, you might need to userm -rf node_modules npm install # or rm -rf node_modules yarn installnpm dedupeoryarn dedupeto try and resolve conflicting package versions, or manually adjust yourpackage.jsonto enforce a single version. - Why it works: When multiple versions of a core library like
react-domare present, the JavaScript runtime can get confused about which implementation to use, leading to unexpected errors like using an old API from one version while expecting behavior from another.
4. Incorrect Import Path for react-dom
- Diagnosis: Double-check the import statement for
react-dom. As shown in fix #2, for React 18, you must import from'react-dom/client'. If you’re still importing from'react-dom', even if you’re usingcreateRoot, the system won’t find the correct functions. - Fix: Ensure your import statement is:
Change any instances ofimport ReactDOM from 'react-dom/client';import ReactDOM from 'react-dom';to this new path when usingcreateRoot. - Why it works: The
react-dom/cliententry point specifically exposes the new APIs required for React 18’s root mounting and concurrent features. The olderreact-dompackage is essentially frozen in time and doesn’t contain these new functions.
5. Using a Package That Hasn’t Updated to React 18
- Diagnosis: This is more of an indirect cause. If a third-party component or library you’re using internally relies on
ReactDOM.renderand hasn’t been updated to usecreateRoot, your entire application might fail. You’ll usually see the error originating from the third-party library’s code in your browser’s developer console. - Fix: Update the problematic third-party package to its latest version. If no update is available, you might need to fork the package, update it yourself, or find an alternative.
If the package is older and unmaintained, you might have to look for a replacement.npm update <package-name> # or yarn upgrade <package-name> - Why it works: By updating the third-party package, you ensure it’s using the correct React 18 APIs, thus resolving the conflict and allowing your application to mount correctly.
6. Using ReactDOM.hydrate Instead of createRoot (Server-Side Rendering)
- Diagnosis: If you’re using server-side rendering (SSR) and see this error, you might be using
ReactDOM.hydrateincorrectly. Similar torender,hydratehas also been updated. - Fix: For SSR with React 18, you should use
hydrateRootfrom'react-dom/client'.
If you are not using SSR, ensure you are usingimport ReactDOM from 'react-dom/client'; import App from './App'; const container = document.getElementById('root'); const root = ReactDOM.hydrateRoot(container, <App />); // Use hydrateRootcreateRootand nothydrateRoot. - Why it works:
hydrateRootis the SSR counterpart tocreateRoot. It initializes React on the client-side by attaching to pre-rendered HTML from the server, preserving the server’s output while enabling client-side interactivity.
After fixing this, the next error you’ll likely encounter is related to the new Suspense features or other concurrent rendering behaviors if your application isn’t fully prepared for React 18’s more advanced capabilities.