Jordan Walke of Facebook originally released React 0.3.0 back in 2013. Since its release, React has become one of the most popular front-end development frameworks among developers. The framework has changed leaps and bounds since that original release. In June 2021, React released a new alpha version of React 18, and finally, in March 2022, the new, stable version was available. React 18 primarily aims to make the user experience more performant by introducing out-of-the-box features and improvements.
In this article, you'll see what the newest version of React brings to the table.
Concurrency
The main point of this upgrade was to focus on concurrency. React 18 makes a distinction between urgent updates and transition updates. An update, in general, is a state change or a function call that takes place in your application and changes things. An urgent update basically would be something like typing or clicking or anything that can be perceived as immediate by the user. Receiving data from an API, for example, can be delayed, but when you're typing on an input, you want to see real-time changes. An update you don't mind waiting for is simply referred to as a transition update; that doesn't mean it will take forever, but if there's an urgent update, you want to prioritize it instead of a transition update.
So what is concurrency? Well, it is not a feature but a behind-the-scenes improvement on how React works. It allows React to prepare multiple versions of the user interface at the same time. Usually, in React, once every render triggers, nothing can stop it, and everything waits for it to render back to the browser. With concurrency, this changes, as any renders can be interrupted, paused, and later start again. You may even stop a render from ever finishing midway.
An example of this could be applying filters to a search result. Instead of waiting for one filter to apply, the UI changes to the page where you can immediately apply another filter on top. The exciting part is it's all happening in the background, and the UI for the user stays consistent while the background job runs. Concurrency also offers a reusable state. With React 18, you can remove parts of the UI from the screen and then later put it back in its previous state. Imagine you have a tab screen, and you move from tab A to tab B. instead of just mounting whatever is inside tab A, you store the UI, and when you click back on tab A, it renders back the appropriate UI previous state.
The new version of React ships with the new concurrent renderer, which indeed is a breaking change to your components. It brings new hooks like the useDeferredValue hook and the useTransition hook that will help defer certain updates while others are prioritized. Ultimately these will change how you develop the front-end and will lead to a much better user experience.
Automatic Batching
Automatic batching in React means that if two states are changed consecutively, the component will only be rendered once. With this feature, React joins multiple setState() calls into only one update to improve performance and doesn't have to spend a lot of time rendering the same work over and over again. React will check the value of a state whenever it changes. If it differs from what it was before, the component will be re-rendered to display the new value. However, if two states are changed in sequence, for example, changing one state in one line of code and then changing another state in the following line, it makes no sense for the component to re-render twice. Because you're changing the state of two different states, they could easily be combined into a single re-render to avoid unnecessary renders.
Automatic batching doesn't require developers to make any changes, which makes it really interesting and straightforward. It works behind the scenes and will run automatically whenever React 18 is installed. Automatic batching was already available in previous React versions, but it just worked in some situations, for example, as a response to browser events such as inside of a function that is called when you click a button. However, now in React 18, automatic batching will occur everywhere regardless of its location. You don't have to do anything about it as it will be done entirely automatically.
For example, it now works with all the asynchronous functions; when you're fetching data, inside of promises, and generally, in any kind of event where two states are changed simultaneously, it will batch these changes and only render once. This is great for small projects, but especially if you are working on a large-scale application where performance matters a great deal, the benefits of automatic batching will be extremely useful.
Server Side Rendering Support for Suspense
Finally, let's take a look at the most significant changes in React 18 that are related to the Suspense component and server-side rendering (SSR). With React 18, developers can finally stream HTML and selectively hydrate the page using Suspense.
Suspense on the server in React 18 is now powered by code splitting as well. That basically means that when you have an app and a certain part of your app is really slow, before React 18, you had to wait for the entire rendering process to be done before you could ship the HTML over to your client.
Let's take a quick look at server rendering before diving into what React 18 introduces. Server rendering means the user creates HTML on the server and then streams it to the client. Server-side rendering requires the client first to fetch all HTML, then load all JavaScript code from the server and hydrate the entire app.
Before React 18, you couldn't split one section of your component away and render the rest separately. There was no middle ground. Imagine your app has a slow part, and you have to wait for the whole app to convert to HTML, slowing down the entire app. With React 18, you can wrap a component into Suspense, which is called suspense on the server.
By wrapping a component in Suspense, you can tell React to wait for it to load and then proceed with the rest of the page. You still send the rest of the HTML, and that component gets a loader state only if you add a fallback spinner. When that component is ready, React sends that HTML in the same stream and all of this happens before any JavaScript is loaded, so it's super-fast for the user, and it decreases the time it takes for the user to see the first page.
React can now make the page interactive before all of the components have hydrated. So, for example, if you have a comments section that is still loading, but the user decides to click on another component, such as a sidebar, React will actually record that click, and after all of the hydration has finished, all of the changes will occur as if the user clicked on the sidebar. As a result, even on low-end devices where hydration can take a long time, the browser can handle events like clicking and typing so that the page does not appear to be stuck.
React 18 also handles the order in which the components on the page are hydrated. This way, the user does not have to worry about things hydrating out of order and ruining the user's experience. As a result, the user benefits from a more interactive page that loads faster rather than having to wait for everything to load before making the page interactive.
Conclusion
React 18 has many new features and improvements that take place behind the scenes and are provided to users right out of the box. Although this version isn't considered groundbreaking, many opportunities have been created for building better, more performant React apps. A number of improvements to the user experience were added in this release, and this particular aspect is expected to improve even further in future releases. Upgrading to React 18 is a relatively straightforward process and won't cause any problems with your existing code.
Interested in using React? Or have thoughts on how React 18 will affect your new project? Solwey can help! Set up a call with us here.