React is set to receive a substantial update with version 19, but before concerns about the learning curve for a new React version start to arise, let me share some reassuring news. React 19 focuses less on the code you need to write and more on reducing the amount of code necessary. This article will cover the key features and improvements introduced in React 19.
New Features Coming in React Version 19 – A Brief Look

🤖 React Compiler
Most of the features that are in react 19 are due to the compiler, so what does it do?
The React compiler transforms your React code into standard JavaScript. It now oversees re-renders, significantly enhancing your app's performance. This means less worry about performance optimization on your part. Essentially, React determines which components need optimization and when, as well as what should be re-rendered, simplifying the development process.

Idempotency in React
One of the foundational aspects that the React Compiler relies on is the principle of idempotency in React components. Idempotency, in this context, means that a React component should return the same output given the same inputs, without side effects such as mutating props or state. This principle is crucial for the compiler's optimization process, as it allows React to automatically re-render just the right parts of the UI when state changes, ensuring efficient updates and performance improvements.
Impact of the New React Version on Idempotency
Introducing the React Compiler in the upcoming version significantly impacts the enforcement and implications of idempotency in React applications. By adhering to the rules of JavaScript and React, including the idempotency of components, developers can leverage the compiler to automatically optimize their applications. This shift means that the manual memoization practices currently used to prevent excessive re-renders (such as useMemo, useCallback, and memo) could become less necessary or even obsolete, as the compiler takes over the optimization process.

Example of use performance hooks before React 19:
tsx
In this example:
useStateis used to track the current filter (filter) and the list of names (names).useCallbackis utilized to optimize the function handling changes in the filter text field, to prevent unnecessary re-rendering.useMemois employed to optimize calculations related to filtering the list of names and calculating the total number of letters in filtered names. This ensures that these calculations are only performed whennamesorfilterchanges, not on every render.
New compiler will optimize your app code automatically, so you can completely remove any performance hook from your code you previously had:
tsx
In react 19 you also no more need to use forwardRef.

We can now pass a ref as a prop and access it just like any other prop, which is a notable enhancement. Observe the change:

💪 Directives and Actions

'use client'
The 'use client' directive in React is used to mark code that should run on the client side. By adding 'use client' at the top of a file, you signal to React and compatible bundlers that the module, along with its dependencies, is intended for client-side execution. This is particularly useful in applications that leverage Server Components, allowing for a clear separation between code that runs on the server and code that runs on the client.
use case
A common scenario for 'use client' is in interactive components that require access to browser APIs or need to maintain their state between renders. For example, a component that includes interactive forms, animations, or access to the local storage must run on the client side.
tsx
Components that directly manipulate the DOM or use browser-specific APIs, such as fetching geolocation, playing audio, or animations using the Web Animations API, should be marked to run on the client.
tsx
Limitations and Disadvantages
- Code Separation: While the
'use client'directive allows for a clear distinction between client-side and server-side code, it also requires developers to manage this division, which can lead to increased complexity in larger applications. - Bundle Size Increase: Code marked to run on the client is sent to the browser, which can potentially increase the size of the client bundle, especially if large amounts of code are designated for client-side execution.
- State Management: Client components are responsible for managing their own state, which can lead to duplication of state logic between the client and the server.
Despite these challenges, the 'use client' directive provides powerful capabilities for optimizing application performance and enhancing user experience by allowing interactive components to run on the client side. By making informed decisions about which parts of an application should operate on the client, developers can strike an optimal balance between performance and feature richness.
use client directive react doc
'use server'
The 'use server' directive allows server-side functions to be callable from the client side, marking them as Server Actions. By placing 'use server' at the top of an async function body, it signals that the function can be invoked by client-side code, making a network request to the server with serialized arguments.
Example of form Action
A common use case for 'use server' is to handle form submissions. For instance, a form that allows users to sign up for a newsletter could call a server action to add the email address to a database.
tsx
Data Mutation
Server actions can also be used for data mutations, such as updating a user profile or posting a comment, where the mutation logic is encapsulated in a server function.
Limitations and Disadvantages
- Asynchronous Execution: Since server actions require a network call, they are inherently asynchronous, which can introduce complexity in managing UI states and feedback for long-running operations.
- Serialization Constraints: Arguments passed to server actions and their return values must be serializable. This limits the types of data that can be sent to and from the server, excluding functions, JSX elements, and other non-serializable types.
- Security Considerations: Because server actions can be invoked with client-controlled inputs, it's critical to validate and sanitize inputs to prevent security vulnerabilities, such as SQL injection or cross-site scripting (XSS).
- Limited by Network Latency: The responsiveness of server actions is subject to network conditions. This can affect the perceived speed of operations initiated by the user, especially in environments with slow or unstable internet connections.
Advantages
- Reduced Client-Side Complexity: By offloading operations to the server, you can simplify client-side logic, especially for operations that involve sensitive data processing or complex transactions.
- Access to Server-Side Resources: Server actions can utilize server-side resources, such as databases or third-party APIs, which are not directly accessible from the client.
- Improved Security: Executing actions on the server allows for better control over security, as sensitive operations and data access can be more tightly controlled and monitored.
The 'use server' directive offers a powerful model for integrating server-side logic into React applications, enabling developers to build more efficient and secure web applications. By thoughtfully applying server actions, developers can enhance the user experience while maintaining the robustness and scalability of their applications.
use server directive react doc
Both directives facilitate the development of applications with a clear separation of concerns between client-side and server-side logic, enhancing efficiency and performance in React applications.
🪝 New React Hooks
The use() hook

The use() hook in React 19, introduces a flexible way to access resources like Promises or contexts within components. Unlike other hooks, it can be used inside loops and conditional statements. This hook is designed to work seamlessly with Suspense and error boundaries, providing a more efficient way to handle asynchronous data fetching and context management
Fetching data before React 19
tsx
In this component, we perform the following steps:
- State Definition: We use the
useStatehook to create states for storing posts, the loading state (isLoading), and any potential errors (error). - Data Fetching: We use the
useEffecthook to perform an asynchronousfetchrequest to the API after the component has loaded. ThefetchDatafunction is asynchronous, allowing the use ofawaitto wait for network responses. - State Management: Depending on the network response, we update the state of the posts, loading, and error. We use
try...catchto handle errors during the request. - Rendering: Based on the state, the component renders information about loading, error, or the list of posts.
Fetching data after React 19 with the use() hook
tsx
In this approach, using new use() hook we perform the following steps:
- Import React Hooks and Components: The code starts by importing the necessary hooks and components from React. This includes the custom
usehook and theSuspensecomponent. - Define the Data Fetching Function: A function named
fetchPostsis defined outside the React component. This function is responsible for fetching data from a remote API (https://jsonplaceholder.typicode.com/posts). It uses thefetchAPI to make a GET request and returns a promise that resolves with the data or rejects with an error. - Use the
useHook to Fetch Data: Within theFetchDataComponent, theusehook is called with the promise returned byfetchPosts. Theusehook reads the value of this promise. It's worth noting that the actual implementation of how theusehook is used with a promise might vary depending on the specifics of your project setup. - Handle Loading State with
Suspense: TheFetchDataComponentis wrapped in aSuspensecomponent in the parentAppcomponent. TheSuspensecomponent is used to display a fallback UI (in this case,<div>Loading...</div>) while the promise is in the pending state. Once the promise resolves, the fallback UI is replaced with theFetchDataComponent's UI, displaying the fetched data. - Map Over the Fetched Data: Inside
FetchDataComponent, the fetched data (assumed to be an array of posts) is mapped over to render a list of posts. Each post is displayed in a list item (<li>) with its title. - Render the Component Tree: Finally, the
Appcomponent (containing theSuspenseandFetchDataComponent) is rendered. When theAppcomponent is rendered, it initially shows the loading state. Once the data is fetched and the promise resolves, the component displays the list of posts.
Read context before React 19
In this example, ThemeContext.Provider enables passing the value "dark" to all components within the tree that consume this context. ThemeComponent reads the context value using useContext.
tsx
tsx
In this example, ThemeContext.Provider enables passing the value "dark" to all components within the tree that consume this context. ThemeComponent reads the context value using useContext.
Read context after React 19
Now, instead of useContext(), we will have use(context).
tsx
Advantages of the use Hook
- Asynchronous Resource Loading: Seamlessly load different resources asynchronously, improving performance and user experience.
- Simplifies Data Fetching: Replaces the
useEffecthook for data fetching tasks, offering a more straightforward approach to making API requests and handling responses. - Context Data Access: It can replace
useContextfor accessing context data, reducing boilerplate and simplifying context management.
Practical Applications
- Data Fetching: The
usehook makes fetching data from an API more intuitive. Coupled with React Suspense, it allows for displaying a fallback UI while data is being loaded, and then seamlessly updating the UI once data fetching is complete. - Context Management: Simplifies reading context data by replacing
useContextwithuse. This makes it easier to consume context in components, further reducing the complexity of React applications.
official documentation of use() hook
The useFormStatus() hook

The useFormStatus hook in React provides insightful status information about form submissions, which is crucial for handling form states and user interactions intelligently. This hook is specifically designed to be used within components that are rendered as part of a form. It returns a status object containing details about the form's submission state.
typescript
How It Works
To effectively utilize the useFormStatus hook, your component, such as a Submit button, needs to be part of a <form> element. The hook taps into the form's submission process, offering properties like pending to indicate if the form is currently being submitted.
Usage
- Parameters:
useFormStatusdoes not accept any parameters. - Returns: The hook returns a status object with several properties:
pending: A boolean indicating if the form is in the process of submitting. Whentrue, it suggests that the form submission is underway.data: An object adhering to the FormData interface, encapsulating the data being submitted by the form. This will benullif no submission is active or if the component isn't within a form.method: A string, either 'get' or 'post', representing the HTTP method the form uses for submission. The method is determined by themethodattribute of the form, defaulting to 'get' if unspecified.action: This refers to the function provided to the form'sactionprop. It will benullif the form is not wrapped by a parent<form>, if theactionprop is set to a URI, or if noactionprop is provided.
Important Considerations
- Form Dependency: It's crucial to call
useFormStatusfrom within a component that resides inside a<form>. The hook is designed to provide status information specifically for a parent<form>and will not work outside this context. - Scope of Status Information: The hook exclusively tracks the submission status of a parent
<form>. It does not extend this functionality to forms nested within the same component or child components.
Example:
tsx
By integrating useFormStatus into your React forms, you can enhance user feedback and control mechanisms during the form submission process, offering a more responsive and informative user experience.
The useFormState() hook
The useFormState hook, offers an innovative approach to managing form state based on the outcomes of form actions. This hook is particularly beneficial when used alongside React Server Components, enhancing the interactivity of forms even before client-side JavaScript fully kicks in.
What useFormState Offers
useFormState enables the creation of component state that updates in response to form actions. By passing an action function and an initial state to useFormState, you receive a new form action and the latest state, which can then be utilized within your form components.
How to Use useFormState
Let's define a simple action function that simulates a form submission, which can either succeed or fail based on the input data. Then, we'll update the StatefulForm component to display messages for success and error cases.
Form Action for Success and Error Simulation
typescript
StatefulForm Component with Success and Error Feedback
tsx
Explanation of the Code
- Action Function (
submitForm): This function simulates a form submission process. It returns a state object containing astatusand amessage. Thestatuscan either besuccessorerror, determined by the submitted form data. - Form Component (
StatefulForm):- Initializes form state using
useFormState, with an initial state indicating that the form is idle. - Renders a simple form with an input field and a submit button. The form submission is handled by
handleSubmit, which creates aFormDataobject and passes it toformAction. - Displays feedback messages based on the form's submission state. Success messages are shown in green, while error messages are displayed in red.
- Initializes form state using
This example showcases how useFormState can be utilized to manage form submission feedback dynamically, improving user experience by providing immediate and relevant responses to their actions.
The useOptimistic hook

The useOptimistic hook in React provides a powerful way to make UIs feel more responsive by optimistically updating the interface ahead of long-running actions, like network requests. This approach is especially useful in scenarios where immediate feedback to user actions is desired, such as submitting forms or updating data.
How useOptimistic Works
useOptimistic allows you to temporarily update the UI based on what you expect to happen, assuming the action will succeed. It takes a piece of state and an update function (updateFn) that defines how to merge the current state with an optimistic update. This hook returns two items:
optimisticState: The state that includes the optimistic update.addOptimistic: A function to call with an optimistic update value.
Example with useOptimistic
Let's create a simple example demonstrating optimistic UI updates when sending a message. The UI will immediately show the message as "Sending..." until the action completes.
tsx
Code Explanation
- State Initialization: The component maintains two state variables:
messagesfor the actual messages andmessageInputfor the current input value. - Optimistic State:
useOptimisticis used to create anoptimisticMessagesstate, which combines the actual messages with any optimistic updates. - Sending Messages: The
sendMessagefunction optimistically updates the UI usingaddOptimistic, immediately showing the message as "Sending...". It then simulates a network request and, upon completion, updates themessagesstate to reflect that the message has been sent. - UI Rendering: The component renders an input form for messages and a list of messages. The list reflects the
optimisticMessagesstate, showing messages as "Sending..." optimistically until the simulated request completes.
This example illustrates how useOptimistic can enhance user experience by providing immediate feedback on actions whose outcomes are expected but have not yet been finalized, making the application feel faster and more responsive.
Here is a summary of the 3 form hooks we learned about

Summary
React 19 introduces a suite of features and improvements designed to enhance developer experience and application performance. At the heart of these advancements is the React Compiler, which optimizes re-renders and overall app efficiency, significantly reducing the need for manual optimization by developers. This new version aims to streamline the development process, allowing for more readable and concise code.
Key Highlights of React 19:
- React Compiler: Central to React 19, it transforms React code into optimized JavaScript, automating performance optimizations and minimizing unnecessary re-renders. This advancement lessens the reliance on manual memoization techniques like
useCallback(),useMemo(), andmemo(). - Simplified Development: The compiler's ability to handle optimization enables developers to write more straightforward component code. An example provided shows the evolution from a version requiring performance hooks for optimization to a cleaner version that eliminates these hooks, thanks to the compiler's optimizations.
- Directives and Actions: React 19 introduces
'use client'and'use server'directives for clearer separation between client-side and server-side logic, making codebases more efficient and organized. The'use server'directive facilitates the implementation of server actions, simplifying data mutations and form submissions. - New React Hooks: A set of new hooks, including
use()for accessing resources,useFormStatus()for form submission status, anduseOptimisticfor optimistic UI updates, further enhance the development experience by simplifying asynchronous data fetching, form state management, and responsive UI creation.
React 19's focus is not on introducing new syntax or concepts that steepen the learning curve, but rather on refining the framework to reduce boilerplate, improve performance, and make React more intuitive for developers. This version represents a significant leap towards more efficient, developer-friendly React applications.
Thank you for taking the time to read through this post. I hope you found the insights shared both valuable and thought-provoking. While this space doesn’t currently feature a comment section, I deeply appreciate your engagement and interest.
May you continue to grow, learn, and inspire those around you.
Cya!
