How to Upgrade to React 18
![How to Upgrade to React 18 banner image's picture](https://cdn.sanity.io/images/aa7yamn6/production/17ae1ac79419cd2cb587d6afea0054b7b87cff35-1200x627.jpg)
React 18 launched earlier this year with some big improvements and exciting features! There are exciting new updates like Concurrent React and Suspense. But, now that we have talked about these features in detail, let us get on with how to upgrade to React 18!
React 18 has several redesigned hooks and features that are especially focused on making the transition to React 18 from older versions to be as painless as possible. You should be able to upgrade to React 18 with minimal effort; ideally under a minute! Let me take you through the steps of upgrading to React 18.
Upgrading to React 18
The upgrading process for React 18 is pretty straightforward. Although most features are introduced keeping in mind easy adoption, several new features like Suspense and Transitions would not work satisfactorily without React 18. Your project must be upgraded to React 18 for you to make the best use of the newest features.
How to upgrade from React 17 to React 18? It can be done in one easy step. You open your project and add the command
npminstall react react-dom
This would automatically upgrade React to the latest version, in this case, React 18.0, on your project. If you are using yarn, then you need to put the command
yarnadd react react-dom
And that is it! React 18 would be automatically installed and your program would be able to utilize the new features.
Once you install React 18, you will receive error messages showing ReactDOM.render is no longer supported in React 18. To eliminate this error, you would need to import the createRoot function from react-dom/client. This would let you unmount and render a new root. Please note that if you skim on this step, your project would continue behaving as if it is still running on React 17. Installing React 18 would have no effects on your code if you do not import the create.Root function!
New Updates You Need to Keep in Mind While Upgrading to React 18
There are some APIs that you would need for your project to run on React 18, even after you have installed React 18. Some functions are also projected to behave differently in the new version. Let us go through them individually.
Client Rendering APIs
- A new root API is introduced in React 18. The primary goal behind this is to improve the general usability and management of roots while coding in React 18. Also, you would need to call the new root API to incorporate the new Concurrent features of React 18 in your project.
1
2
3
4
5
6
7
8
9
10
// 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); // createRoot(container!) if you use TypeScript
root.render(<App tab="home" />);
- In React 18, unmountComponentAtNode has been changed root.unmount
1
2
3
4
5
// Before
unmountComponentAtNode(container);
// After
root.unmount();
- Callback in render was speculated and then observed to not work properly with Suspense, a new feature in React 18. For this reason, the callback function is removed from render in React 18. There is no direct substitution for the render callback API at the moment.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// Before
const container = document.getElementById('app');
render(<App tab="home" />, container, () => {
console.log('rendered');
});
// After
function AppWithCallbackAfterRender() {
useEffect(() => {
console.log('rendered');
});
return <App tab="home" />
}
const container = document.getElementById('app');
const root = createRoot(container);
root.render(<AppWithCallbackAfterRender />);
- ReactDOM.hydrate is substituted by hydrate.root in React 18. In case your project requires hydration in server-side rendering, you would need to import hydrate.root in the new version of React.
1
2
3
4
5
6
7
8
9
10
// Before
import { hydrate } from 'react-dom';
const container = document.getElementById('app');
hydrate(<App tab="home" />, container);
// After
import { hydrateRoot } from 'react-dom/client';
const container = document.getElementById('app');
const root = hydrateRoot(container, <App tab="home" />);
// Unlike with createRoot, you don't need a separate root.render() call here.
Stricter Strict Mode
The <StrictMode>
is even more strict in React 18! Possibly, some of your projects will not work after you upgrade them to react 18. To bypass this problem, you would have to check if the projects not working with React 18 are wrapped in <StrictMode>. If they are, removing Strict Mode during the process of upgrade might help in making your older apps work with React 18. After the upgrade is done, you can again wrap your code, or a part of it in strict mode. That is, only after removing issues that were causing your code to not work!
It is important to note here that there are plans for future versions of React to have better responsiveness to UI inputs. To root out any issues that might surface from introducing these updates, a development-only check is added to the Strict Mode in React 18. This feature will be automatically unmounting and remounting every component in your code during the initial mounting of the component. The previous state of the component would be remounted during the second mount.
1
2
3
4
5
6
7
8
9
* React mounts the component.
* Layout effects are created.
* Effect effects are created.
* React simulates unmounting the component.
* Layout effects are destroyed.
* Effects are destroyed.
* React simulates mounting the component with the previous state.
* Layout effect setup code runs
* Effect setup code runs
Server Rendering APIs
- Allreact-dom/server APIs are redesigned in React 18 so that they can support Suspense completely on the server as well as Streaming SSR. The old Node streaming API has been deprecated for this reason. This was done because this API did not support server streaming of Suspense incrementally. Using the Node Streaming API will now generate the warning: renderToNodeStream
- To stream in Node environments, we would now have to use renderToPipeableStream
- Additionally, a new API is introduced to support streaming on server-side rendering with Suspense in environments like Deno and Cloudflare: renderToReadableStream
- The following APIs now have limited functionality with Suspense, although they still work:
- renderToString
- renderToStaticMarkup
- The renderToStaticNodeStream API would still function for email rendering.
Updated Typescript Definition
If you are using TypeScript for your project, you would have to make some changes when you upgrade to React 18. The most important change is updating the @types/react
and @types/react-dom
dependencies in React 18. These are comparatively safer and are more likely to detect problems.
Another important change is that now you would need to explicitly list the children prop while listing props. See the following example:
1
2
3
4
5
interface MyButtonProps {
color: string;
children?: React.ReactNode;
}
Automatic Batching
Automatic Batching is a whole new feature that has been added to React 18. To enable automatic batching in your project, you would simply have to import create.root and your code will be automatically batched by React 18.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// After React 18 updates inside of timeouts, promises,
// native event handlers or any other event are batched.
function handleClick() {
setCount(c => c + 1);
setFlag(f => !f);
// React will only re-render once at the end (that's batching!)
}
setTimeout(() => {
setCount(c => c + 1);
setFlag(f => !f);
// React will only re-render once at the end (that's batching!)
}, 1000);
If you do not want automatic batching for your code in React 18, you can import flushSync.
1
2
3
4
5
6
7
8
9
10
11
12
import { flushSync } from 'react-dom';
function handleClick() {
flushSync(() => {
setCounter(c => c + 1);
});
// React has updated the DOM by now
flushSync(() => {
setFlag(f => !f);
});
// React has updated the DOM by now
}
Library APIs
New APIs have been introduced in React 18 keeping in mind library maintainers. The APIs would allow using concurrent rendering, a new feature of React, for specific uses. Let us briefly discuss these APIs.
- useSyncExternalStore enables concurrent reads of external stores making sure that any updates to the store are synchronous.
- useInsertionEffect enables CSS-in-JS libraries to resolve performance issues associated with injecting styles during rendering.
Configuring Testing Environment
In the previous sections, we have covered the changes that you might need to make in your code for it to work once you upgrade to React 18. In this section, we shall talk about the changes you would have to consider in the testing environment while working on React 18.
Your test console would show you this error when you try to upgrade your tests using create.root, The current testing environment is not configured to support React 18.
To get around this error, you would have to mark globalThis.IS_REACT_ACT_ENVIRONMENT as true.
This would tell React that your code is running in a unit-test-like environment. If you mark this flag as false, react will not mark warnings when an update is not wrapped in act.
Deprecated APIs
Although we have already talked about all the APIs that are deprecated in React 18, let us still have a look at the whole list of deprecated APIs in React 18 as a form of recapitulation. Please keep in mind to not use these APIs once you upgrade to React 18. Your code will either not work, or it would run in React 17 if you use these.
react-dom: ReactDOM.render
react-dom: ReactDOM.hydrate
react-dom: ReactDOM.unmountComponentAtNode
react-dom: ReactDOM.renderSubtreeIntoContainer
react-dom/server: ReactDOMServer.renderToNodeStream
Wrapping Thing Up
React 18 comes with several new features that work interdependently to provide an improved responsivity of codes written using this newest version of the library. Upgrading to React 18 is very simple and should not take more than a few seconds. However, to upgrade our older codes to React 18 and then use all the new features of this version, we would have to make some changes in the code. To make this process a no-brainer, React has introduced several new APIs that we can simply import into our code. This would enable our code to use React 18 completely. Certain APIs are also deprecated as they are substituted by the new APIs. As long as you keep in mind these, upgrading to React 18 is going to be a cakewalk.
There are several new exciting changes to the React library that came with React 18. Upgrade to the newest version and have fun playing around!
![Sam Dutta's picture](https://cdn.sanity.io/images/aa7yamn6/production/3e4b98ffb7117348b315070b7d535b11b9df9d2d-80x80.png?w=72)
Sam took the long path into the world of IT. A post-grad in Bioinformatics, she started coding to build better programs for protein sequencing. Currently, Sam actively writes blogs for 4 Way Technologies. She's always excited about all the new technologies and updates in software development. Sam also writes coding tutorials and beginners guides for, well, beginners.