React 18 upgrade guide and new features

React 18 upgrade guide and new features

React 18 is the most recent major React release. It introduces a number of fundamental concepts while requiring no major code changes.

React 18 was out in March of 2022, and while updating to this new version should only need small code changes, it nevertheless offers several exciting new concepts and provides a solid foundation for React's future. As was announced, this update is primarily concerned with performance enhancements and the upgrading of the rendering engine.

React is a JavaScript user interface library developed by Facebook that has garnered significant interest in the front-end development community. React 18 is its most recent major version, and it offers features such as automated batching, new APIs, and streaming server-side rendering with suspense support.

As stated, React 18 provides a foundation for concurrent rendering APIs, on top of which new React features may be built.

It has a number of new features that we'll go over briefly in this tutorial, including the principles of concurrent rendering, batching, and transitions. It also introduced new hooks such as useId, useTransition, useDeferredValue, useSyncExternalStore, useInsertionEffect. We’ll also learn how to upgrade to React 18.

This upgrading method is intended to get your application running on React 18 while without causing any of your previously written code to become unusable. Following that, you may gradually begin to include concurrent functionality at your own pace.

As a whole, you want to make the transition to React 18 as easy as possible. Then you may go at your own speed and begin to build concurrent functionality.

Concurrent rendering with React 18

Until React 18, prior versions of react used synchronous rendering — once an update begins rendering the user interface, it cannot be stopped until the user sees the results of the update on the screen.

React 18 serves as the cornerstone for a new journey, with the goal of making it easier for developers to build outstanding user experiences with distinctive performance using features built on top of concurrency.

As a consequence, React 18 includes additional features backed by a new concurrent renderer capability. Concurrent rendering is a promising new feature in React, and the majority of the new features, such as suspense, transitions, and streaming server rendering, will be designed to make use of it.

Concurrent React's ability to render without interruption is a fundamental feature. After upgrading to React 18 and before employing any concurrent features, the UI updates in React 18 are still executed in a single, continuous, synchronous process, as they were in prior versions.

React 18 concurrency is the most major change, but it’s new behind the curtains feature that is hidden from developers, yet it is critical due to the power it provides and the new set of features it unleashes.

As a react developer, you will not be much exposed to the changes just like the other advanced mechanisms employed by react such as priority queues and multiple buffering

In its underlying implementation, React employs advanced mechanisms such as priority queues and multiple buffering. However, you will not find such concepts in the public APIs.

React 18 new features

React 18 delivers additional functionality and new features driven by a new concurrent renderer.

When it comes to new features in React 18, many of them are based on the new concurrent renderer that was introduced by the react team. Despite the fact that concurrent React is an optional feature, it will have a significant influence on the way developers design apps in the future.

React server components

Developers will be able to build applications that bridge both the server and the client thanks to a new feature called server components.

Although Server Components is still in its infancy, the React team plans to release an initial version in a minor 18.x release. Meanwhile, they're working with frameworks like Next.js, Hydrogen, and Remix to improve the concept and make it more widely applicable.

In the future, developers will be able to develop apps combining robust interactivity with improved server rendering performance. Server Components isn't inherently related to concurrent React features like Suspense or streaming server rendering, but it's built to complement them.

Automatic batching

Batching is when React combines many state updates into a single re-render. React leverages batching to combine several state changes into a single re-render for better performance.

By default, React 18 is equipped to do more batching than previous versions, which helps to improve performance.

React 18’s createRoot method will batch all updates, regardless of where they come from. To put it another way, every event-related update will be batch-processed in the same manner as updates made within React events.

Even though it's a breaking change, they anticipate it to improve performance in your apps since it reduces the amount rendering.

The flushSync API may be used to turn off automatic batching.

New enhancements to Suspense on servers

Suspense is a react component that allows you to declare the loading state for a region of the component tree that isn't yet ready to be rendered with a fallback option.

React 18 introduced server-side support for Suspense and increased its capabilities with concurrent rendering features.

In this version, react-dom/server APIs was redesigned to fully accommodate Suspense on the server and Streaming SSR. As part of these improvements, the old Node streaming API, which does not enable incremental Suspense streaming on the server, was retired in favor of the new API.

Suspense works best in React 18 when paired with the transition API. Suspending during a transition prevents already-visible content from being replaced by a fallback. React will instead wait the render until enough data has been loaded to avoid a bad loading state:

<Suspense fallback={<Loading />}>
  <App />
</Suspense>

New Rendering APIs for the client and server

React 18 brings a new root API which supports improved usability for handling roots. The new root API also supports the new concurrent renderer, allowing you to optionally use the new concurrent capabilities.

In React 18, new APIs were added for rendering on both the client and server. These updates enable developers to continue using the old APIs in React 17 mode while upgrading to the new APIs in React 18.

These new APIs are now available through the react-dom/client package:

  • createRoot: You call this new method to create a root where React renders and mounts. It is designed to be used in place of ReactDOM.render. This method is necessary for new features in React 18 to function.
  • hydrateRoot: You can call this new to hydrate a server-rendered application. Utilize it in place of ReactDOM.hydrate with the new React DOM Server APIs. Without it, new features in React 18 will not function.

This is how createRoot should be used:

import { createRoot } from 'react-dom/client';
const container = document.getElementById('app');
const root = createRoot(container); // createRoot(container!) if you use TypeScript
root.render(<App />);

Both createRoot and hydrateRoot now take a new argument called onRecoverableError for notifying you when React recovers from rendering or hydration failures for logging purposes. By default, React will utilize reportError() or, in earlier browsers, console.error().

They have also changed unmountComponentAtNode to root.unmount.

A new API was added to provide streaming SSR with Suspense for modern edge runtime environments, such as Deno and Cloudflare workers.

These additional APIs are now exposed from react-dom/server and provide complete server-side support for streaming Suspense:

  • renderToPipeableStream: used in Node contexts for streaming.
  • renderToReadableStream: used in current edge runtime environments like Deno and Cloudflare workers.

The existing renderToString method is still functional, although it is not recommended.

New hooks

React 18 introduced new hooks such as useId, useTransition, useDeferredValue, useSyncExternalStore, and useInsertionEffect.

useId

Using the new useId hook, you can generate client- and server-side unique IDs without having to worry about hydration discrepancies.

React 18's new streaming server renderer makes this hook much more useful since it transmits HTML out-of-order.

useTransition

useTransition and startTransition allow you to indicate certain state updates as not urgent. Other state updates are automatically marked urgent by default. React will enable non-urgent state changes to be interrupted by urgent state updates (for example, changing a text input).

How to upgrade to React 18

First things first, It’s important to understand that new concurrent rendering is only activated on areas that make use of the new features of React 18. In this section, we will take you through the procedures for upgrading to React 18.

You can progressively implement concurrent rendering in your existing apps since it’s breaking change that makes rendering interruptible and by consequence makes components operate somewhat differently.

If your application contains a lot of components, you will notice that most of them still work when upgrading to React 18 and shifting to concurrent rendering but some of them may not and you’ll have to do further updates that should be minor anyway and you’ll be able to make them at your own speed.

Your main upgrading plan should aim to get your application working on React 18 without causing any problems with current code. Then, at your own pace, you may begin incrementally adding concurrent features.

Your application should be compatible with React 18 without creating any issues with your present code, which is the primary goal of the upgrade strategy.

Afterwards, you may start adding concurrent features one by one at your own speed, as you see fit. It won't catch everything, but it does a fair job of avoiding the most common types of mistakes, which is a good thing.

Open a new command-line interface and navigate to your React 17 project. Then, start by installing the latest version of react as follows:

npm install react@18 react-dom@18

Next, open the src/index.js file of your app or where the entry point of your app exists and update the import declaration of ReactDOM as follows:

import ReactDOM from 'react-dom/client';

Following that, you need to replace render with createRoot.

In the same index.js file of your project, and start by updating ReactDOM.render to ReactDOM.createRoot to create a root, and render your app as follows:

import ReactDOM from 'react-dom';
import App from 'App';

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

// create a root
const root = ReactDOM.createRoot(container);

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

That's it, you'll be able to use concurrent capabilities after these updates! You may, for example, utilize startTransition to navigate between screens without interfering with user input. Furthermore, you may utilize useDeferredValue to limit expensive re-renders.

Also, if your app is server-side rendered with hydration, you need to upgrade hydrate to hydrateRoot.

Moreover, during development, you may utilize <StrictMode> to aid in the discovery of concurrency-related errors. Strict Mode has no effect on the functionality of the application in production, but it will generate additional warnings and double-invoke functions that are supposed to be idempotent during development.

Obviously, it will not capture everything, but it is quite successful at avoiding the most prevalent sorts of errors.

Conclusion

To conclude, React 18 builds the groundwork for future releases while concentrating on enhancing the user experience.

React 18's UI updates are executed in the same way as in prior versions—in a single, continuous, synchronous process—when you initially upgrade to version 18 and before employing any concurrent features. It is impossible to halt synchronous rendering until the user actually sees the result.

Numerous features in React 18 are built on top of the new concurrent renderer, a feature that takes place in the background yet provides access to a wide range of strong new possibilities.

Upgrading to React 18 should be easy, and your existing code should not break as a consequence of the change.