---
title: React 18 Upgrade Guide and New Features
description: React 18 was released! Are you looking to upgrade to React 18?  Learn about the new features and changes in this comprehensive guide.
slug: react-18-upgrade-guide
authors: joel_adewole
tags: [react]
image: https://refine.ams3.cdn.digitaloceanspaces.com/blog/2022-09-09-react-18/social.jpeg
featured_image: https://refine.ams3.cdn.digitaloceanspaces.com/blog/2022-09-09-react-18/featured.png
hide_table_of_contents: false
---

## Introduction

Since updates frequently include modifications that changes features completely or even eliminate certain features and add others, some developers may find it difficult to transition between different versions of libraries. It is better to use the most recent versions of libraries to get the best performance possible.

You can either create a new React project or reinstall React in an existing project to migrate from **React 17 to React 18**.

This article will discuss what **React 18** is, issues with React 17, new features in React 18, and reasons why you should use the most recent version. You should be familiar with JavaScript, React, and NPM to follow along with this article.

Step we'll cover:

- [What is React 18](#what-is-react-18)
  - [Upgrading to React 18](#upgrading-to-react-18)
- [Issues with React 17](#issues-with-react-17)
- [What changed in React 18](#what-changed-in-react-18)
  - [Client Rendering](#client-rendering)
  - [Hydration](#hydration)
  - [Render Callback](#render-callback)
  - [Automatic Batching](#automatic-batching)
  - [Transitions](#transitions)
  - [Dropped support for Internet Explorer](#dropped-support-for-internet-explorer)
- [Benefits of React 18 over React 17](#benefits-of-react-18-over-react-17)

# What is React 18

Before we look into **“What’s new in React 18”**, what does React 18 mean?
Any stable version of the React library from 18.0.0 upwards but not including 19.0.0 is known as React 18.

The creation of React 18 introduced concurrent rendering in React applications. React has been taking care of DOM rendering and giving developers tools to control and track component lifecycle. With some new capabilities, React 18 can now adapt the rendering process to suit client devices.

## Upgrading to React 18

The React community offers a variety of installation options. To install React 18 in your application, you can use the CDN URL as the source(src) in an HTML script tag.

```html
  <!-- Load React. -->
  <!-- Note: when deploying, replace "development.js" with "production.min.js". -->
  <script src="https://unpkg.com/react@18/umd/react.development.js" crossorigin></script>  <script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js" crossorigin></script>
  <!-- Load our React component. -->
  <script src="app.js"></script>
</body>
```

By executing the following commands in a terminal of your working directory, you can upgrade or **install React 18** using NPM or Yarn for single-page and bundled applications.
For NPM:

```
npm install react react-dom
```

For Yarn:

```
yarn add react react-dom
```

The above commands will automatically detect and install or upgrade the most recent React and React DOM versions in your development environment.

# Issues with React 17

The React community has noticed some issues or problems with the library which require improvement. \*\*React 18 and higher versions wouldn't need to be released if React 17 was functioning flawlessly.

According to **the changelog of React 18.0.0**, the following issues with React 17 or earlier were addressed:

- Render throws an error if `undefined` is returned: When a component returns a value of `undefined`, the application will break.

The application displays the following error:

<br/>
 <img src="https://refine.ams3.cdn.digitaloceanspaces.com/blog/2022-09-09-react-18/firstError.png" alt="firstError" />

<br/>

You will also notice the error below in your console:

<img src="https://refine.ams3.cdn.digitaloceanspaces.com/blog/2022-09-09-react-18/secondError.png" alt="secondError" />

<br/>

- `setState` of unmounted component gives a warning: In an attempt to update the state of an unmounted component, React might warn you of a memory leak.

<img src="https://refine.ams3.cdn.digitaloceanspaces.com/blog/2022-09-09-react-18/thirdError.png" alt="thirdError" />

<br/>

- Strict mode console log suppression: From community feedback, it was noticed that the suppression of the console log message when using Strict Mode creates confusion since only one shows instead of two.

- Memory consumption: React 17 and earlier had issues with memory leaks, especially in unmounted components.

# What changed in React 18

More emphasis is made on application concurrency in React 18. This idea includes functions such as Automatic Batching, Transition, and Suspense, as well as APIs like createRoot, hydrateRoot, renderToPipeableStream, and renderToReadableStream. It also includes hooks such as useId, useTransition, useDeferredValue, useSyncExternalStore, and useInsertionEffect, as well as updates on Strict Mode and the deprecation of `ReactDOM.render` and `renderToString`.

Let’s take a deeper look at these changes 👀:

## Client Rendering

You might want to keep an eye out for the console warning listed below after an upgrade:

 <img src="https://refine.ams3.cdn.digitaloceanspaces.com/blog/2022-09-09-react-18/clientError.png" alt="clientError" />

<br/>

If you continue to use the `ReactDOM.render()` API supported in React 17; you will see this warning. Typically, we import a component and render it inside a div element with the id=app".

<br/>

```javascript
import ReactDOM from "react-dom";
import App from "App";

const app = document.getElementById("app");

ReactDOM.render(<App />, app);
```

In React 18, as in the following code sample, we use the `createRoot()` API imported from "react-dom/client":

```javascript
import { createRoot } from "react-dom/client";
import App from "App";

const app = document.getElementById("app");

// create a root
const root = createRoot(app);

//render app to root
root.render(<App />);
```

## Hydration

React 17 used the `ReactDOM.hydrate()` API for rendering with hydration, as in the following code sample:

```javascript
import * as ReactDOM from "react-dom";
import App from "App";

const app = document.getElementById("app");

// Render with hydration.
ReactDOM.hydrate(<App tab="home" />, app);
```

In React 18, hydration uses the `hydrateRoot()` API imported from “react-dom/client” and doesn’t require a separate `render()` method as in the code snippet below:

```javascript
import { hydrateRoot } from "react-dom/client";

import App from "App";

const app = document.getElementById("app");

const root = hydrateRoot(app, <App tab="home" />);
```

## Render Callback

You could pass a callback function when rendering the root component so that it would execute after the component renders or updates.

In the render method of React 17, you could pass a callback function as the third argument, as in the code snippet below:

```javascript
import * as ReactDOM from 'react-dom';
import App from 'App';

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

ReactDOM.render(app, <App tab="home" />, function() {
  // Called after initial render or any update.
  console.log('Rendered or Updated').
});
```

The callback function is not allowed in **React 18** because it affects the application's runtime with progressive or partial hydration. Instead, you could use a ref callback, `setTimeout`, or `requestIdleCallback` on the root element, as in the code example below:

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

function App({ callback }) {
  // Callback will be called when the div is first created.
  return (
    <div ref={callback}>
      <h1>Hello World</h1>
    </div>
  );
}

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

const root = createRoot(app);
root.render(<App callback={() => console.log("Rendered or Updated")} />);
```

## Automatic Batching

State updates were only batch processed in React event handlers before version 17. Therefore any state updates made outside of event handlers resulted in a re-render, which required React to perform additional background tasks. For instance:

```javascript
const handleClick = () => {
  setFirstState(“1”);
  setSecondState(“2”);
}
```

React will only re-render in the code snippet above once all the states have been changed at the end of the event callback function. Otherwise is the case for state updates in promises, native events or outside React event handlers. For instance:

```javascript
fetch(‘https://api.com’).then(() => {
  setFirstState("1");
  setSecondState("2");
})

//OR

setTimeout(() => {
  setFirstState("1");
  setSecondState("2");
})
```

In the code snippet above, React will re-render for each state update.

The `createRoot()` API in React 18 enables batching all state updates, regardless of where they happen in the application. React then re-renders the page after all state-updates.

Since this is a breaking change, you can stop automatic batching using the `flushSync()` API.

```javascript
import { flushSync } from "react-dom";

function handleClick() {
  flushSync(() => {
    setFirstState("1");
  });

  flushSync(() => {
    setSecondState("2");
  });
}
```

In the code snippet above, each instance of `flushSync()` updates state and allows React to re-render.

## Transitions

You can use Transitions to distinguish between resources that need urgent/immediate state updates and those that do not.

The functionality of the search bar is a good example. While a user types the search word, you might want to display visual feedback. However, you don't want the search to start until the user has finished typing.

```javascript
import { startTransition } from "react";

// Urgent: Show what was currently typed
setSearchCurrentValue(input);

startTransition(() => {
  // Not-urgent: Show what was finally typed
  setSearchFinalValue(input);
});
```

In the code snippet, instead of using `setTimeout()` which will delay state updates, we used `startTransition()` to monitor the state update. `setSearchCurrentValue()` only updates the state that is concerned with the feedback we want the user to get immediately, the `setSearchFinalValue()` updates the state we want to use to eventually make the search when the user has finished typing.

Unlike `setTimeout`, `startTransition` updates can be interrupted, can track a pending update, and it executes immediately.

## Dropped support for Internet Explorer

The React community has also dropped support for Internet Explorer which means that only browser feature up until React 17 will work on Internet Explorer. Modern browser features such as multitasks, `Promise`, `Object.assign` or `Symbol` won’t be pollyfilled in Internet Explorer.

<br/>
<div>
<a href="https://discord.gg/refine">
  <img  src="https://refine.ams3.cdn.digitaloceanspaces.com/website/static/img/discord_big_blue.png" alt="discord banner" />
</a>
</div>

# Benefits of React 18 over React 17

Even after learning the **differences between React 17 and React 18**, you may still be unsure about switching to React 18 or sticking with React 17.

A new version won't be appreciated if it doesn't provide more benefits over previous ones.

Concurrency is one of React 18's main advantages. It is a brand-new concept, not a feature, that enables React apps running on React 18 and higher to optimize their performance on client devices.

By clearing out background tasks on unmount, React 18 enhances memory management and lowers the danger of memory leaks.

# Conclusion

You should be able to update your React version and refactor your codebases to seamlessly use **React 18** after reading this tutorial.

To get the most recent information on changes and new releases, you should also keep a close eye on the React library changelogs for updates and stay in touch with the React community.
