React v18 has finally been released after being talked about since 2021. React v18 brings exciting new features to improve performance and the user experience. The main emphasis of this release was the introduction of concurrent Mode, new hooks, and improvements to React’s strict mode API.
The information in this article is organized based on the table presented by Shruti Kapoor at the Reactathon 2022 conference. It will cover three key features of React v18: automatic batching, transition, and suspense on the server. It will also touch on the concept of concurrency and the new APIs introduced in React DOM Client and Server. Lastly, it will also introduce the new hooks available in React v18, including useId and useTransition.
With the new React version, we have access to features like automatic batching, which combines multiple state updates into a single re-render, transition, which distinguishes between urgent and non-urgent updates, and suspense on the server, which improves performance even for slowly rendered components.
Automatic Batching – Optimizing Performance Through Minimal Re-Rendering
Shruti Kapoor uses the example of grocery shopping to illustrate the concept of ‘automatic batching’ in React. This means making a list of all the items you need for cooking and getting them all in one trip to the grocery store rather than making multiple trips. In React, batching refers to reducing the number of re-renders (trips) that occur when multiple states change.
Previously, state updates that occurred outside of event handlers, such as API calls or promises, were not batched. Still, with React v18, all state updates can be automatically batched, including within promises, setTimeouts, and event callbacks. This results in a significant reduction in the amount of work that React has to perform in the background.
Automatic batching is only available if you use createRoot instead of the render method when mounting your app. If you prefer not to use automatic batching, you can opt-out by using flushSync.
Transition – Enhancing User Experience With Delayed Loading
React has a new concept called “transition,” which distinguishes between urgent and non-urgent updates. Transition updates change the UI as a user switches from one view to another in a non-urgent manner, whereas urgent updates are instantaneous answers to direct user interaction (clicking, typing, etc.)
useTransition hook or startTransition method starts the transition, and these are considered low-priority updates. They will be discontinued if more pressing updates, like clicking or pressing keys, happen. In case the user interrupts the transition, for instance, by typing several characters in quick succession, React will only render the most recent update and stale any previous rendering work that was not completed.
Transitions can be used in situations where either rendering is slow, or the network is slow. In the case of slow rendering, React performs a significant amount of work, and marking updates as transitions can help optimize the process. In the case of a slow network, React can wait for data from the network without freezing the UI, improving the user experience.
Suspense on the Server – Leveraging Suspense for Server-side Data Loading
React v18 introduces “suspense on the server,” which enhances the performance and user experience of server-side rendering. Code splitting with suspense, which allows developers to split their components into smaller pieces and load them independently, enables faster initial load times and reduced resource usage on both the server and the client. Streaming rendering on the server sends the initial HTML to the client as soon as it’s available rather than waiting for the entire page to finish rendering. This results in a faster and smoother user experience, as users see the initial content of the page sooner.
In React v18, Suspense for data fetching could be used by opinionated frameworks such as Relay, Next.js, Hydrogen, or Remix. However, the use of Suspense data fetching without frameworks is not currently recommended. While React is exploring the possibility of providing further tools in the future to access data with Suspense, it is believed that libraries and frameworks will continue to play an important role.
Concurrency – Optimizing Performance and User Experience
“Concurrent React,” a new mechanism that allows the preparation of multiple versions of the UI at the same time. Concurrency is not a feature itself but a behind-the-scenes implementation detail that enables new features (like Suspense and the new startTransition() and useDeferredValue() APIs, etc.
Before React v18, render transactions were always single, uninterrupted, and synchronous, making it impossible to interrupt the process. With this new feature, React can pause, resume, interrupt, or even abandon a render if necessary. That is concurrency; if a task is long, you can pause it, switch to another one, complete it, and then continue. This allows for a more responsive experience for the user, even when React is in the middle of a complex rendering task.
React DOM Client
The following new APIs have been introduced in react-dom/client:
A new method to create a root for rendering or unmounting. It should be used instead of ReactDOM.render and enables concurrent features from React v18.
This is a new method to hydrate a server-rendered application. It should be used in conjunction with the new React DOM Server APIs instead of ReactDOM.hydrate.
React DOM Server
The renderToPipeableStream API is specifically designed for use in Node environments, while the renderToReadableStream API is optimized for modern edge runtime environments like Deno and Cloudflare Workers. The traditional renderToString method remains functional, but its usage is discouraged.
UseId is a new hook that generates unique IDs on the client and server while preventing the need to manually manage ID values and ensuring consistency between renders.
The useTransition and startTransition hooks in React v18 categorize state updates into two categories – urgent and non-urgent. By default, state updates are considered urgent, but these hooks allow you to mark certain state updates as non-urgent. This means that React will prioritize and allow important updates, such as updating a text input, to interrupt the less urgent ones, like rendering a list of search results.
The useDeferredValue hook allows you to delay the re-rendering of a non-critical component. Unlike debouncing or throttling, there is no set time delay, meaning React will attempt the deferred render immediately after the first render appears on the screen.
In conclusion, React v18.0 brings a lot of exciting improvements to enhance the performance and user experience. With the introduction of the Concurrent Mode, the concept of concurrency has allowed React to become more responsive and user-friendly. Additionally, automatic batching, transition, and suspense on the server are key features that allow React to optimize performance and also allow for the preparation of multiple versions of the UI at the same time, enabling new features like Suspense and new APIs. With the introduction of React v18, developers can take advantage of faster rendering, optimized performance, and enhanced user experiences.