Jun 20, 2024, Web

React 19 – New Features You Need to Know!

Rafał Ticman Frontend Developer
megaphone in a hand
React 19 is about to see the light of day, and with it comes a host of exciting new features that could revolutionize the way user interfaces are created. If you're a developer or simply passionate about the technology, you can't miss this breakthrough. Compiler, enhancements and fresh hooks make React 19 more versatile and powerful than ever before. Dive into the world of the latest version of React with us and discover how it can make your work easier and more efficient. Find out what makes React 19 a real game-changer in the world of front-end development!

React Compiler

What is the React Compiler?

The React Compiler is an innovative feature introduced in React 19, designed to enhance the optimization processes of React applications. It aims to automate the optimization steps that developers typically handle manually, significantly improving the efficiency and performance of applications.

The react compiler allows you to automate memoization by using a built-in cache ensuring that only relevant parts of the application are rendered as its state changes. This way, developers don’t have to worry about manual optimization.

How does the React Compiler Work?

The React Compiler works by analyzing the application code during the compilation process to JavaScript. It scans for areas where memoization can be applied and automatically implements these optimizations. The build contains pre-optimized and memoized code, ready for efficient client-side execution. By preventing the re-rendering of components that do not need to change, React can deliver more efficient rendering and state updates, which significantly improves overall application performance. This pre-optimization reduces runtime overhead, resulting in faster and more efficient applications. Unlike previous versions where optimizations were handled at runtime, the React Compiler now shifts this responsibility to the build phase, aligning React with modern practices seen in frameworks like Vue.

Sample React component:

image

React component after compilation:

image


What did the compiler do?

React Compiler analyzed the component code and applied automatic memoization to optimize its performance. Here’s what it changed:

  • Adding a cache ($): The compiler added the $ variable as a caching mechanism that stores the component’s rendering results.

  • Checking for state changes: The $[0] variable stores the previous count state value. The compiler added an if condition to check if the count value has changed since the last rendering.

  • Memoizing the render result: If the count value has changed, the variable t0 is set to the new render result, which is stored in $[1]. If count has not changed, the compiler uses the memorized rendering result from $[1].

This way, the component renders again only if the count has changed, minimizing the need to recalculate unchanged data and improving application performance.

React Compiler Playground:  https://playground.react.dev/

How was it before?

React Compiler ensures that the client-side receives already optimized and memoized JavaScript code. This pre-optimization reduces the runtime overhead, resulting in faster and more efficient applications. Unlike previous versions where optimizations were handled at runtime, the React Compiler moves this responsibility to the build phase, aligning React with modern practices seen in frameworks like Vue.

The main purpose of React Compiler is to automatically memoize code. Before React 19, we had access to memoization through APIs such as useMemo, useCallback and React.memo. These APIs allow us to mark portions of our application that do not need to be recalculated until the corresponding values have changed. Although memoization is a powerful feature, it is easy to forget about it or apply it incorrectly. Keep in mind that memoization also has a cost and thus used in an inappropriate way can result in degraded optimization.

React 18 example:

image

React 19 example:

image

Use API

What is the use hook?

Hook use was created to standardize the async API, which would allow smooth/linear handling of asynchronous data. Using server components, we have access to await, which can only be used in asynchronous functions. Unfortunately, for technical reasons, client components cannot be asynchronous, so use is the recommended way to handle asynchronous resources.

What hook use can do?

Simplified Asynchronous Handling

The use hook allows you to directly use promises within your components. When a promise is passed to the use hook, React can automatically handle the suspension and error boundaries. This makes it much easier to work with asynchronous data fetching and other async operations.

image

Flexible Context Reading

Similar to useContext, the use hook can read values from context. However, unlike useContext, it can be called inside loops and conditional statements, providing greater flexibility in your component logic.

image

Integration with Suspense

When used with promises, the use hook integrates seamlessly with React’s Suspense feature. This ensures that your components can display fallback content while waiting for data to load, resulting in smoother user experiences.

image

Actions

What are React 19 actions?

In React 19, we are introducing support for the use of asynchronous functions in transitions to handle wait states, errors, forms and optimistic updates automatically.

Previously, support for asynchronous operations such as requests to the server, form handling and optimistic updates often required manual management of various application states. For example, you had to handle the states of waiting for a response from the server, errors, and state updates on your own based on optimistic assumptions that the operation would succeed.

The introduction of support for the use of asynchronous functions in transitions in React 19 aims to make it easier to handle these operations through automatic state management. Asynchronous functions can be used in transitions to perform operations, such as sending requests to the server or handling form operations, making it possible to respond to different stages of these operations in an intuitive way.

For instance, an asynchronous function can handle server requests and automatically manage responses and errors, eliminating the need for manual state updates. This enhancement significantly improves the efficiency and transparency of managing asynchronous operations within React applications.

Actions APIs (useOptimistic, useFormStatus, useActionState) facilitate form operations. In SSR they additionally allow you to submit a form with JS disabled, this makes it easier to reduce the amount of javascript on pages.

useOptimistic()

Hook useOptimistic to optimistically update the user interface before the server returns an acknowledgment. This allows users to experience a smoother interaction without having to wait for the server to respond. This is especially useful in situations where you want to immediately show the user the results of their actions, even if the server has not yet responded.

Before actions example:

image

Example with useOptimistic hook:

image

In React 18, managing optimistic updates requires additional logic to synchronize state with the server and deal with any errors. React 19 simplifies this process with the introduction of useOptimistic, which automates many of these steps.

useFormStatus()

The useFormStatus hook is used to manage the status of form fields, including handling validation logic and submission status. It provides information about the status of the last form submission, making it easier to manage forms by providing a centralized mechanism for monitoring and modifying the status of individual form fields.

Before actions example:

image

Example with useFormStatus hook:

image

In React 18, managing form status required creating separate states for submission and success and updating them in the appropriate places. In React 19, useFormStatus simplifies this process, providing more readable and concise code.

useActionState()

The useActionState hook in React 19 is a tool for managing the state of asynchronous actions in React applications. It allows you to more easily monitor and control different states such as wait, success or error when performing asynchronous operations such as API requests. Below is a more detailed description of how it works.

Before actions example:

image

Example with useActionState hook:

image

Painless forward ref

How has it worked so far?

forwardRef in React allowed passing refs to function components, which was crucial for getting references to DOM elements in function components.

image

Adding forwardRef to a component introduces additional complexity, especially for new developers and in large base codes. Testing components with forwardRef is more difficult because it requires additional setting of refs in unit tests. Code with forwardRef can sometimes be less readable because refs must be passed and handled inside function components.

How will it be now?

Starting in React 19, you can now access ref as a prop for function components.

image

New function components will no longer need forwardRef, and we will be publishing a codemod to automatically update your components to use the new ref prop. In future versions we will deprecate and remove forwardRef.

Server Components

Server Components in React 19 allow components to be processed on the server before the site is delivered to users. This results in faster page loading and better SEO optimization. This is a significant improvement because it reduces the amount of JavaScript that must be sent to the client, which improves performance, especially on slower networks.

React Server Components (RSC)

React server components are components that execute 100% on the server side, that is, all the logic of the component including the dependencies used is executed on the server side and the client gets the result of the component. This way the client does not download the needed dependencies(much smaller bundle size).

Sample Server Component:

image

Code returned from the server:

image

What is the difference with SSR?

SSR allows you to speed up the initial loading of the page by generating and returning to the client static HTML, but the client still needs to download the rest of the js that is needed to make our application interactive. In the case of react server components the server doesn’t return static HTML but intermediate code understood by react that tells it how to merge the updated data with the current state of the client-side component. Thanks to such merging, we get the state from the server while maintaining the state on the client side.

Web Components

Web Components are a standard set of web technologies that allow you to create custom user interface components that are platform-independent and can be used in various frameworks and libraries, including React.

In React 19, web components can be integrated and used in React applications just like in other web applications. React allows you to create and use web components by using standard mechanisms such as HTML tags.

Document metadata

How to manage document metadata?

This makes it easy to control document metadata, such as page title, meta tags and other header elements. This is particularly beneficial for SEO and improving user experience, as it allows you to dynamically adjust the metadata depending on the state of your application.

React 19 automatically handles hoisting these tags to the <head> section, ensuring they appear in the document’s metadata. This approach works seamlessly with client-side rendering, server-side rendering (SSR), and streaming SSR (experimental).

image

Comparison with React 18

In React 18, you had to manage meta tags manually using:

  • External libraries like react-helmet

  • Custom effects with libraries like react

  • Manual creation of elements with name and content attributes

image

Asset Loading

Asset loading in React 19 allows you to load files in the background, which significantly improves application loading times and user experience. This functionality provides more control over the asset loading process, which can have a big impact on the overall performance of the application.

This can include:

  • Lazy Loading: The ability to delay the loading of certain resources, such as images outside of the user’s view, to speed up the initial page load and reduce network bandwidth consumption.

  • Code Splitting: Further development of code splitting tools that allow only necessary portions of an application to be loaded in response to user actions, contributing to faster loading times and better performance.

  • Prefetching: The ability to load resources in the background that may be needed in the future, such as when viewing different sections of an application, to provide smoother transitions between views.

  • Cache Management: Resource cache management tools that can help minimize the amount of resources that need to be reloaded by the browser, leading to faster application loading for repeat users.

With these improvements, React 19-based applications can achieve better performance and a more responsive user experience through smarter resource loading management.

Better Support for TypeScript

TypeScript is becoming increasingly popular among JavaScript developers, and React continues to expand support for the language.

New features in TypeScript Support:

  • Advanced typing for components and hooks: More accurate type definitions for props and states, making it easier to create error-free code.

  • Developer Tools: Better integration with developer tools such as React DevTools, which can display types directly in the interface.

  • Documentation and examples: Enhanced documentation with more examples and tutorials on using TypeScript with React.

Improved Developer Tools

New versions of React DevTools will offer more advanced features for debugging and profiling applications.

What’s new in React DevTools?

  • Type preview: Ability to preview props and state types directly in developer tools.

  • Performance profiling: Better tools for analyzing application performance to help identify bottlenecks and optimize code

Summary

The article highlights that React 19 introduces substantial changes and new features; however, it has not been officially released yet. It is advisable to use it primarily for learning and experimentation rather than deploying it in production applications. It is important to stay informed about its development progress by regularly checking the official React documentation and following the development repository on GitHub, where developers are actively enhancing this version.

Share