🎉Celebrating 25 Years of Tech Excellence and Trust - Learn More

React 18: A Guide to Its New Features and Updates

Updated : Oct 19, 2022
What’s New In React 18?
TezJS for Jamstack Web Apps

The hottest topic and buzzword in the JavaScript community right now is React 18. Finally, after a long wait, the React team has announced the latest version of React – React v18.0 with its highly-anticipated concurrent rendering features.

In short, it’s going to give tough competition to the TezJS framework, which is also responsible for building UI components.

Last year, in June 2021, the React team announced the upcoming launch of React 18 and what was to come. In December 2021, the prime focus of React Conf 2021 was the newly launched concurrent rendering features of React.

On This Page
  1. React is Design Oriented
  2. What is React 18 Concurrent Mode?
  3. New Suspense Features
  4. Streaming Server Rendering
  5. Automatic Batching
  6. Transitions
  7. New Client and Server Rendering APIs
  8. Strict Mode Behaviors
  9. New Hooks
  10. Upgrade to React 18

From the initial level, every developer in the React team has been very cautious about out-of-the-box improvements like new APIs (startTransition), automatic batching, and streaming server-side rendering with support for Suspense and upgrades to the React community.

As a result, they created a React 18 working group, where they invited experts, tech leaders, and developers from various communities to participate and share their knowledge to make React 18 better and more consistent. The primary aim of the group was to work collaboratively towards the seamless functionalities, features, libraries, and applications for React 18.

Many of the new features in React 18 are based on the new concurrent renderer, which is a behind-the-scenes upgrade that unleashes powerful new capabilities. Concurrent React is an opt-in feature that is only active when using a concurrent feature, but it will significantly impact how users design the apps.

Now, the React 18 release date is officially rolled out; the official version of React 18 is available in the market along with React 18 features, updates, and functionalities. It will surely redefine the ReactJS development services in the coming days.

But no need to worry if the older version of React is still part of your project as this new React v18 doesn’t break your existing code if you are planning to upgrade.

So, without any further ado, let’s walk through React 18 new features.

React is Design Oriented

The APIs of React are rooted primarily in design principles, not programming!

In this technology-driven world, many emerging tech companies help to bridge the gap between developers and designers with innovations. Therefore, one of the renowned React engineers - Andrew Clark, stated at React Conf 2021 that React 18 features are based on the design principle.

In addition, he quoted,

With React, designers and developers speak the same language.

Talking about React JS 18, it has an amazing UI focus that catches the attention of designers and development teams. Therefore, they embrace React v18, highlight it in their presentation, and actively collaborate with designers and other UI/UX specialists to improve the library.

Looking for Experienced React Developers for Hire?

Hire Right Away!

What is React 18 Concurrent Mode?

Concurrent is one of the most important features in React 18 that has solved an age-old ignored issue. Actually, concurrency is not a feature. It works as the back-stage function that encourages React to create multiple versions of your UI concurrency simultaneously.

React is used to design APIs, and it covers the implementation details from development teams.

They believe that React developers should concentrate on how React features will help them accomplish the user experience they desire for their clients. React will surely help you achieve an amazing user experience.

Albeit Concurrent React is not just about a specific implementation detail, it’s a fundamental React update to its core rendering model, which helps to understand how Concurrency React works in React18.

While not migrating to React 18 or not adding any concurrent features, every update was rendered in a single, synchronous, and uninterrupted transaction. However, the major issue every developer used to face was that with the start of asynchronous rendering transaction, nothing could interrupt it until the users could see the result on the screen. This doesn’t happen every time in concurrent rendering.

React can start rendering an update, pause in the middle, and continue later. It may even abort a rendering that is in process. React ensures to offer a consistent UI even if the render is interrupted. This method allows React to develop new screens in the backend process without blocking the main thread. It means that even if the UI is in the middle of a massive rendering operation, it may respond to user input quickly, resulting in fluid user experience.

Another advantage of concurrent mode is the reusable state. With the help of Concurrent React, React can easily omit the sections of the UI from the screen and add them back while reusing the previous state.

Let’s understand with an example here.

When a user moves to the other tabs and returns to the original tab, React will be able to restore the previous screen in the same state as it was before. However, React 18 is going to have a new component called <Offscreen> to implement this pattern.

New Suspense Features

Suspense is a React component that allows developers to pause the rendering of a component until a given condition is met, with a fallback option. A string or another React component - a spinner - can be used as a fallback option. React Suspense had only worked with dynamic importing up until now (lazy loading).

React allows us to achieve server-side rendering by first rendering all the components on the server. Then the result must be sent to the browser as HTML elements.

React will load JavaScript as usual in the browser. The HTML components generated by the server will then be connected to JavaScript.

We can see the page content before the JavaScript bundle loads and runs using server-side rendering (SSR).

In React, the suspense feature will postpone component rendering. With certain limitations and basic support for suspense rendering, it was first introduced in React version 16.6.

The stable version of React 18 will have a full suspense feature based on the concurrent feature, as well as the following:

  • Delayed transition: It informs the components to hold on making a new state transition until the data has been resolved.
  • Placeholder throttling: It actually reduces UI thrash by slowing the visibility of nested place holder and subsequent placeholder components.
  • SuspendList: It assists with the suspension of multiple components by placing them in the order in which they must be revealed to the user.

The React version 18 handles suspense differently from the prior versions. However, the impact of the change is minimum with the automatic batching. It will have no substantial impact on the app's migration to React version 18.

In the previous versions – React 16 and 17, the suspense feature was referred to as legacy suspense. In React 18, the better and enhanced suspense is called concurrent suspense.

Apart from resolving the ComponentThatSuspends function, both the legacy and concurrent suspense features provide the same basic user experience, as shown in the following example.

<Suspense fallback={<Loading />}>
<ComponentThatSuspends />
<Sibling />
</Suspense>

The above example shows how a suspense component will work in the React 18 version:

  • The Sibling component will be mounted to the DOM right away by the legacy suspense. Its lifecycle hooks/effects will also be triggered. It will not wait for the ComponentThatSuspends to be resolved before proceeding.

  • Until the ComponentThatSuspends is resolved, the concurrent suspense will not mount the Sibling component to the DOM, and its lifecycle hooks/effects will not be fired. This new feature will fix all of the problems with legacy suspense.

Streaming Server Rendering

Server rendering is a unique technique where the HTML output of the React component is rendered and notified to the users before JavaScript is ready. Before the release of React 18, this was an all-or-nothing situation: the page would update, and the user could begin interacting with the application once all of the components were available. That meant that if you had only one slow component, such as a complicated data grid, it might become a bottleneck.

Server Rendering

Since React 18 comes with Suspense, it allows us to designate fallbacks for UI elements that are yet to be seen on the screen. Therefore, using the <Suspense> tags, we could wrap a single slow component and delay the component loading. Also, you can configure fallback to show a loading animation.

Suspense on the server

Instead of waiting for everything to be ready, this allows the user to see the content on the page as soon as it becomes available. You can immediately display the initial HTML and then stream the rest!

Automatic Batching

Batching is an integral part of React for grouping state updates with the help of inbuilt hooks and event handlers. This will help prevent components from re-rendering for all state modifications unnecessarily, resulting in improved speed. Batching was only available for browser events until the previous version - React 17. With the new React 18 release, React introduces 'Automatic Batching,' an improved version of batching.

Automatic Batching enables batching for all state updates from createRoot, regardless of where they originate. This has batch state changes, intervals, native event handlers, asynchronous operations, and timeouts.

Automatic Batching of React 17:

function App() {
//Declaring state values.
Const [count, setCount] = useState(0);
const [flag, setFlag] = useState(false);

// Change state on button click.
function handleClick() {
setCount(c => c + 1); // Does not re-render yet
setFlag(f => !f); // Does not re-render yet
// React will only re-render once at the end (that’s batching!)
}

return (
<div>
<button onClick={handleClick}>Next</button>
<h1 style={{ color: flag ? “blue” : “black” }}>{count}</h1>
</div>
);
}

Regardless of where the state updates come from, React 18 will batch them all together. As a result, whether an update is contained within a setTimeout, promise, native event handler, or any other event, the React 18 version will batch it similarly to changes contained within React events. In comparison to prior React versions, this will increase the app's efficiency and result in fewer component re-renderings.

Automatic Batching of React 18:

function App() {
const [count, setCount] = useState(0);
const [flag, setFlag] = useState(false);

function handleClick() {
fetchSomething().then(() => {
// React 18 and later versions batch these state updates with single rerendering.
setCount(c => c + 1);
setFlag(f => !f);
// React will rerender once at the end (that's batching!)
});
}

return (
<div>
<button onClick={handleClick}>Next</button>
<h1 style={{ color: flag ? "blue" : "black" }}>{count}</h1>
</div>
);
}

React 18 allows batch state updates inside setTimeout, native event handlers, promises, or any other event.

Stopping Automatic Batching with flushSync()

Now that we've learned about the advantages of automated batching in terms of eliminating needless rendering in React 17 and earlier versions, it's also crucial to have the means to disable automatic batching for code that relies on reading anything straight from the DOM when the state changes. Therefore, React 18 has ReactDom.flushSync() that helps developers to stop automatic batching.

import {flushSync} from ‘react-dom’; // Note: from react-dom, not React
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
}

Be the Game Changer with React Frontend Tool

Let’s Get Technical!

Transition

React introduces a new concept called Transition to distinguish between urgent and non-urgent updates. It aids developers in prioritizing updates that they expect their consumers to interact with more frequently.

Urgent updates show direct interactions such as pressing, clicking, and typing. Transition updates that transition the user interface from one view to the next.

When dealing with real objects, urgent updates require a quick response to match the user's intuition and experience. If there’s a bit of delay when they press a button, it throws them off because they expect a prompt answer.

Users are more patient with transition updates because they understand that their activities, like navigating from one page to another, may not result in an immediate reaction on screen.

For example, when a user hits a drop-down menu button, they want the drop-down menu to display immediately, even though the contents of the drop-down menu may load with a tiny delay, which is understandable. Users will be patient with updates, especially if you categorize the data according to new attributes.

So, single-user input should result in both an urgent and non-urgent update if you wish to give the best user experience. Developers can use the start transition API within an input event in React 18 to instruct React which updates are urgent and which aren't.

import {startTransition} from ‘react’;

// Urgent: Show what was typed
setInputValue(input);

//Mark any state updates inside as transitions
startTransitions (() => {
// Transition: Show the results
setSearchQuery(input);
});

Here non-urgent will consider wrapped updates inside start transition. It will only interrupt the transition if there’s an occurrence of an urgent update from the user’s side, like click events or keypress. If the user interrupts the transition, React will drop the unfinished mid-rendering task and focus on rendering the most recent urgent update.

The following are the two ways to start transitions that React 18 offers:

  • useTransition

It’s a transition hook that includes a value for tracking the pending state.

  • startTransition

Developers can use this approach to start transitions when hooks aren't accessible.

New Client and Server Rendering APIs

React 18 has redesigned the APIs to render on the client and server sides. The new APIs allow users to continue utilizing the old React 17 APIs while upgrading to the new React 18 APIs.

React DOM Client

react-dom/client exports the given new APIs:

  • createRoot

It’s a new method that lets you create a root to unmount or render. You can use this method in place of ReactDOM.render. In React 18, new features don’t work without it.

  • hydrateRoot

It’s a new method to hydrate a server-rendered application. You can use it in place of ReactDOM.hydrate in conjunction with the new React DOM Server APIs. In React 18, new features don’t work without it.

If you wish to be notified when React recovers from errors during hydration or rendering for logging, both createRoot and hydrateRoot go for a new option called onRecoverableError. React will utilize reportError by default or console.error in older browsers.

React DOM Server

react-dom/server export new APIs and offers full support for streaming Suspense on the server:

  • renderToPipeableStream

It’s used to stream in Node environments.

  • renderToReadableStream

It’s for modern edge runtime environments, like Deno and Cloudflare workers.

The renderToString method is still functional, although it is discouraged.

New Strict Mode Behaviors

React 16.3 introduced a Strict Mode to React community. The tool was used to define the coding patterns that could cause issues with concurrent rendering APIs of React. It executes in development mode and displays error messages or code suggestions to help developers improve their code.

When developers add <StrictMode> to a React app, it gives all the wrapped components a unique behavior. For example, when developers run React in 'strict mode', React will re-render all components to flush out any potentially dangerous effects.

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 effects are created.
  • Effects setup code runs.

Planning to Upgrade Your React JS App?

Make No-regret Moves

New Hooks

And last but not least, React 18 has new hooks for React developers. In fact, React hooks have been in the market since October 2018. The new hooks enable developers to develop class-based components as an alternative. Moreover, it encourages React developers to build the whole app with the help of React functional components. This allows developers to execute simpler scripts that more quickly and effectively perform similar functions.

Many new React hooks have been introduced with React 18, which are as follows:

useTransition

startTransition and useTransition consider state updates as not urgent. So, by default, other state updates are regarded as urgent. React will allow non-urgent state updates (for example, rendering a list of search results) to be interrupted by urgent state updates (for example, changing a text input).

useId

useId is a new hook that avoids hydration mismatches while producing unique IDs on both the client and server. It's most beneficial for component libraries that need to integrate with accessibility APIs that require unique IDs. This fixes a problem that existed in React 17 and earlier, but it's even more critical in React 18 due to the new streaming server renderer's out-of-order HTML delivery.

useDeferredValue

You can use useDeferredValue to defer re-rendering a non-urgent component of the tree. It works similarly to debouncing, although it offers a few advantages. React will attempt the deferred render directly after the initial render is reflected on the screen because there is no predetermined time delay. The deferred render is interruptible and does not prevent the user from making a selection.

useSyncExternalStore

The new hook useSyncExternalStore forces synchronous updates to external stores, allowing for concurrent reads. It eliminates the requirement for useEffect when creating external data subscriptions and is recommended for any library that integrates with a state outside of React.

useInsertionEffect

The useInsertionEffect hook helps CSS-in-JS libraries to handle performance difficulties with injecting styles in the render. It’s not needed to use until there’s already a CSS-in-JS library. This hook will execute once the DOM is changed, but before the layout effects have had time to read the new layout. This fixes a problem that existed in previous React version 18 but is now even more critical in React 18 because React yields to the browser during concurrent rendering, allowing it to recalculate layout.

So, was React v18.0 able to impress you? If yes, then what’s stopping you?

Upgrade to React 18

Migrate and upgrade your existing React to React 18 and leverage the benefits of all the features and functionalities in the application. Get a head start now and hire React JS developers from Radixweb to try your hands on React 18.

Don't Forget to share this post!

Jaydeep Patadiya is a AVP - Sales at Radixweb and always has the answer to- what's on the mind of the customers? In an industry that is fundamentally changing, he helps customers make the right decisions by connecting the right dots and adopt new technologies. Beyond work, he prepares for upcoming marathon races.