212

I get this error every time I create a new React app:

Warning: ReactDOM.render is no longer supported in React 18. Use createRoot instead. Until you switch to the new API, your app will behave as if it's running React 17. Learn more: https://reactjs.org/link/switch-to-createroot

How can I fix it?

I created my React app using:

npx create-react-app my-app
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
SnNaCk
  • 2,370
  • 2
  • 5
  • 16

15 Answers15

365

In your file index.js, change to:

import React from "react";
import ReactDOM from "react-dom/client";
import "./index.css";
import App from "./App";
import reportWebVitals from "./reportWebVitals";

const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>
);

reportWebVitals();

For Typescript

Credit from comment section below answer: Kibonge Murphy

import React from "react";
import ReactDOM from "react-dom/client";
import "./index.css";
import App from "./App";
import reportWebVitals from "./reportWebVitals";

const root = ReactDOM.createRoot(document.getElementById("root") as HTMLElement);
root.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>
);

reportWebVitals();
Federico Baù
  • 6,013
  • 5
  • 30
  • 38
4l3x1
  • 3,674
  • 2
  • 5
  • 4
  • 63
    For typescript support ``const root = ReactDOM.createRoot(document.getElementById("root") as HTMLElement);`` – Kibonge Murphy Apr 01 '22 at 12:43
  • 1
    @KibongeMurphy I get the following warning when adding what you recommended. `This assertion is unnecessary since it does not change the type of the expression.sonarlint(typescript:S4325)` Any ideas why? – CWSites Aug 23 '22 at 16:52
  • The versions you're running would be helpful to understand what's happening... For now, it looks like you don't need the explicit casting. Try removing the ``as HTMLElement`` – Kibonge Murphy Aug 25 '22 at 19:10
  • For reference check this: https://reactjs.org/link/switch-to-createroot – Nena Dec 02 '22 at 13:42
  • 1
    now i get `react-dom.development.js:86 Warning: You are importing createRoot from "react-dom" which is not supported. You should instead import it from "react-dom/client"` – java-addict301 Dec 22 '22 at 06:44
  • I get this warning from `npx create-react-app` and updating react and react-dom, running ǹpm audit fix [--force]` doesn't even fix the vulnerabilities. Who ships a broken version of React? What a fiasco. – Rin and Len Jun 06 '23 at 12:50
60

React 18 shipped March 29th, 2022. ReactDOM.render has been deprecated in React 18 and currently issues a warning and runs in a compatible mode.

Deprecations

Deprecations

  • react-dom: ReactDOM.render has been deprecated. Using it will warn and run your app in React 17 mode.
  • react-dom: ReactDOM.hydrate has been deprecated. Using it will warn and run your app in React 17 mode.
  • react-dom: ReactDOM.unmountComponentAtNode has been deprecated.
  • react-dom: ReactDOM.renderSubtreeIntoContainer has been deprecated.
  • react-dom/server: ReactDOMServer.renderToNodeStream has been deprecated.

To resolve it, you can either revert to a previous version of React or update your index.js file to align with the React 18 syntax.

Example:

import { StrictMode } from "react";
import { createRoot } from "react-dom/client";

import App from "./App";

const rootElement = document.getElementById("root");
const root = createRoot(rootElement);

root.render(
  <StrictMode>
    <App />
  </StrictMode>
);
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Drew Reese
  • 165,259
  • 14
  • 153
  • 181
  • 4
    This is a good answer. But if, like me, you're using Typescript, you will need to add something like ``` if (!rootElement) throw new Error('Failed to find the root element') ``` before calling createRoot. – kevinrutherford Apr 01 '22 at 15:08
  • 6
    For typescript users, the only thing you need to do is add "devDependencies": { "@types/react-dom": "^18.0.0" }. That's it. The code above with createRoot is fine. – Joe Apr 08 '22 at 19:35
  • 1
    @matdev Yes, move whatever `Link` components you are rendering inside any router component you are rendering. This has nothing to do with React 18. See [error useHref() may be used only in the context of a component](https://stackoverflow.com/a/70220520/8690857). If you need more help from here it preferable to create a *new* SO post with the specific details and [mcve]. Feel free to ping me here with a link to the post if you like, and I can take a look when available. – Drew Reese Mar 29 '23 at 14:48
38

Instead of:

import ReactDOM from 'react-dom'
ReactDom.render(<h1>Your App</h1>, document.getElementById('root'))

Use:

import { createRoot } from 'react-dom/client'
createRoot(document.getElementById('root')).render(<h1>Your App</h1>)

More details here

JohnPix
  • 1,595
  • 21
  • 44
16

Before

import { render } from 'react-dom';
const container = document.getElementById('app');
render(<App tab="home" />, container);

After

import { createRoot } from 'react-dom/client';
const container = document.getElementById('app');
const root = createRoot(container);
root.render(<App tab="home" />);

Before in your index.js file:

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';

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


reportWebVitals();

Change it like below into your index.js file:

import React from 'react';

import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';

import { createRoot } from 'react-dom/client';
const container = document.getElementById('root');
const root = createRoot(container);
root.render(<React.StrictMode>
  <App />
</React.StrictMode>);


reportWebVitals();
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
  • 3
    It is not easy to see the diff. And an explanation would be in order. E.g., what is the idea/gist? From [the Help Center](https://stackoverflow.com/help/promotion): *"...always explain why the solution you're presenting is appropriate and how it works"*. Please respond by [editing (changing) your answer](https://stackoverflow.com/posts/71762741/edit), not here in comments (***without*** "Edit:", "Update:", or similar - the answer should appear as if it was written today). – Peter Mortensen Apr 15 '22 at 11:52
7

To provide more or less an equivalent to prior versions of React, I use this slightly condensed version of the above, still surrounding the <App> with the <React.StrictMode>.

Another reason I condense this is that - in my specific pipeline - I never need to access the root variable, consequently, chaining statements together makes more sense to me, and the whole file is just five lines of code:

import React from 'react';
import ReactDOM from "react-dom/client";

import './index.css';
import App from './App';

    ReactDOM.createRoot(document.querySelector("#root")).render(<React.StrictMode><App /></React.StrictMode>);

(P.S.: Don't forget if you need the webvitals functionality to also add to the above code)

Finally, I save this starter code as a Live Template using the WebStorm IDE. Depending on your IDE your snippets may be called differently, but the idea should be similar.

QRrabbit
  • 330
  • 3
  • 14
6

As your error states, ReactDOM.render is no longer supported. So use the new createRoot.

As you can see from the code below, (which was pulled from the documentation) all you have to do is replace ReactDOM.render with createRoot.

// Before
import { render } from 'react-dom';
const container = document.getElementById('app');
render(<App tab="home" />, container);

// After
import { createRoot } from 'react-dom/client';
const container = document.getElementById('app');
const root = createRoot(container);
root.render(<App tab="home" />);
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Dylan L.
  • 1,243
  • 2
  • 16
  • 35
6

As you said, you created your React app using: npx create-react-app my-app.

  • Your index.js must look like this after the command executes.

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';

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

reportWebVitals();
  • Your code after edits mentioned in the console

import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';

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

reportWebVitals();
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
heetboda10
  • 79
  • 1
  • 3
  • 1
    your "runnable" code cannot run in stackoverflow with `import` statements – vsync Jul 18 '22 at 11:34
  • While you are right that "Your index.js must look like this after the command executes." the question remains: Why does create-react-app bootstrap an application with an error in it? It's a brand new app running the latest version. Is there a reason behind the developers shipping it in a broken state? – Rin and Len Jun 06 '23 at 13:01
6

The legacy root API with ReactDOM.render has been deprecated in React 18 and replaced with a new root API using createRoot. The root of your app is the top-level DOM element that contains all of your rendered components, and is usually a <div> with an ID of root.

React 18 still has support for ReactDOM.render so you technically aren't required to update, but you can't be sure how long this support will last.

You can find a lot more information on the difference between ReactDOM.render and createRoot at https://thelonecoder.dev/javascript/react-js/reactdom-render-vs-createroot/.

To update to the new root API, change your index.js file to something like the following:

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

const root = createRoot(document.getElementById('root'));
root.render(<App />);
christian_js
  • 298
  • 3
  • 11
  • The warning says your application is going to be behaving as React 17, is this not actually required to trigger the React 18 ? – Rolando Niubó Jun 22 '23 at 20:03
5

In your index.js file:

import React from "react";
import ReactDOM from "react-dom/client";
import App from "./App";

Use this before React version 18

// ReactDOM.render(
//   <React.StrictMode>
//     <App />
//   </React.StrictMode>,
//   document.getElementById("root")
// );

Use this in React version 18

const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(<App />);
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Manish Bhusal
  • 91
  • 1
  • 4
3

This should do it:

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

const root = createRoot(document.getElementById("root"))
root.render
  (
    <App />
  )
  • An explanation would be in order. E.g., what is the idea/gist? From [the Help Center](https://stackoverflow.com/help/promotion): *"...always explain why the solution you're presenting is appropriate and how it works"*. Please respond by [editing (changing) your answer](https://stackoverflow.com/posts/71698440/edit), not here in comments (***without*** "Edit:", "Update:", or similar - the answer should appear as if it was written today). – Peter Mortensen Apr 15 '22 at 11:51
3

If your application is using React-Router, then the following code will work fine:

import { createRoot } from "react-dom/client";
const container = document.getElementById("root");
const root = createRoot(container);
root.render(
  <BrowserRouter>
    <App />
  </BrowserRouter>
);

It will work perfectly (with react-router).

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Saha Anik
  • 31
  • 1
  • Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Apr 06 '22 at 09:11
  • Since I'm new to React, I'm not sure if this is a relevant question, but it looks like the element Id won't always be 'root'. In that case, it seems the createRoot() call would probably be something else. Is there a more general answer? – MiguelMunoz Apr 09 '22 at 04:51
1

In React 18. For those that are using custom Webpack configurations, follow React Refresh Webpack Plugin. They have some HMR built in.

We are supposed to use fast refresh that has been developed by the React team.

It resolved that error message for me.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Ballpin
  • 217
  • 2
  • 6
0
import React, {createRoot} from "react";
import ReactDOM from "react-dom/client";
import App from "./App";
import "./styles.css";


const root = ReactDOM.createRoot(document.getElementById("app"));
root.render( <App />);
0

Use:

import ReactDOM from "react-dom/client";

const element = document.getElementById("root");

// Tell React to take control of that element
// In TypeScript, since there is a bug, you need to add the "!" element!
// https://github.com/DefinitelyTyped/DefinitelyTyped/issues/43848
const root = ReactDOM.createRoot(element!);


const App = () => {
  return (
   <React.StrictMode>
    <div>
      <h1>Hello world!</h1>
    </div>
   </React.StrictMode>
  );
};

root.render(<App />);
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Yilmaz
  • 35,338
  • 10
  • 157
  • 202
  • An explanation would be in order. E.g., what is the idea/gist? From [the Help Center](https://stackoverflow.com/help/promotion): *"...always explain why the solution you're presenting is appropriate and how it works"*. Please respond by editing, not here in comments. – Peter Mortensen Sep 18 '22 at 18:52
-1

Use:

import React, { useEffect } from "react";
import { createRoot } from "react-dom/client";

const App: React.FC<{}> = () => {
  useEffect(() => {
    fetchOpenWeatherData("Toronto")
      .then((data) => console.log(data))
      .catch((err) => console.log(err));
  }, []);

  return (
    <div>
      <img src="icon.png" />
    </div>
  );
};

const rootEl = document.createElement("div");
document.body.appendChild(rootEl);
const root = createRoot(rootEl);
root.render(<App />);
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
  • 2
    Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Sep 02 '22 at 22:24