React Tutorial: React 18 upgrade guide
React Tutorial has recently been updated to React 18.
Read this blog post to learn how to upgrade from React 16 to React 18.
This article is split into two sections. Upgrade steps and Changes overview
I. Upgrade steps
Start by navigating to your React 16 (or 17) project. Make sure your git status is clean (or that you have a backup).
1. Upgrade the react libraries
Then, update the react
and react-dom
packages by running npm install react@latest react-dom@latest
You can go back to serving your project (npm run start
if you're using create-react-app). Everything should continue working.
However, you should see a warning in the console saying that ReactDom.render is deprecated. Your app will still work. But it won't be using the new Concurrent features described below.
2. Use the new ReactDOM root API
In your index.js
, you will find the code that uses ReactDOM's render
method. This needs to be changed.
Start by adding the following import:
import { createRoot } from 'react-dom/client';
Then, use the new createRoot
API as shown below:
const container = document.getElementById('root');
const root = createRoot(container);
root.render();
Finally, remove the old render
call and remove unused imports.
This is how the code would look like in the index.js
once you've completed the upgrade:
import React from "react";
import { createRoot } from 'react-dom/client';
import App from "./App.jsx";
import * as serviceWorker from "./serviceWorker";
const container = document.getElementById('root');
const root = createRoot(container);
root.render(<App />);
// serviceWorker.register();
3. Remove StrictMode if you're using React Router
React Router v5 currently breaks with StrictMode. Until this is fixed, you may need to remove <StrictMode/>
if you're using it.
You're done! Your app is now running in React 18!
II. Changes overview
As you can see, upgrading to React 18 should be straightforward. Below we'll discuss some other changes you can make to your React 16 project.
1. JSX works without importing React
This is a feature introduced by React 17. You don't necessarily need to import React
anymore to use JSX. So, if you'd like, you can get rid of the React
imports where you only need them for JSX.
You still have to import useState
or React
if you have other code that depends on them. For example, React.useState
.
2. Components can now render undefined
In Chapter 11, we mention that your component cannot return undefined
. Instead, you would have to return null
.
As of React 18, you can now return undefined
.
3. StrictMode is more strict
StrictMode may produce new errors. This is normal as it has become more strict about warning if a component might break in Concurrent React.
4. Concurrent React
React has made many internal changes to how renders work. This is a low-level change that you should not have to worry about. It will, however, open the door for many new features and performance improvements. You can read more about it in the release post.
The new rendering behavior in React 18 is only enabled in the parts of your app that use new features.
5. Automatic batching
This is another internal change that will have performance benefits on your app. Previously, multiple state updates were batched, as explained in the course. However, multiple state updates inside .then()
callbacks, setTimeout
callbacks, and event listeners were not batched.
As of React 18, they will be batched as you'd expect. For more information, refer to the release post.
6. Transitions (new feature)
React 18 introduced a new feature. React predicts that in a couple of months, you won't have to use the feature yourself. Instead, it will be used by libraries you use (such as React Router).
Transitions allow you to deprioritize some updates that are not critical to the user interface. For example, if the user is typing in a search box and you're sending fetch requests on every keystroke, the setValue
on the input
element has to update immediately. Otherwise, the UX feels glitchy. Whereas the code that performs the search does not necessarily need to happen immediately. For that, you can use the new startTransition
and wrap non-urgent updates with a transition.
Check out the release post for a sample code.