# React 19: Top New Features & Developer Benefits

> 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.

- URL: https://www.maciejbednarczyk.com/en/blog/react-19-top-new-features-and-developer-benefits
- Author: Maciej Bednarczyk
- Language: en
- Published: 2024-04-07

## New Features in React 19 - A Brief Look

![react mind](https://assets.cmssy.io/6ae4795c65113d877fc8d877/295bfa23-c14f-4a0f-910c-f1be143b38b9-374a66b4d0c5.png)

## 🤖 React Compiler

The React Compiler is a separate build-time tool, not part of React 19 itself, and it is released on its own. So what does it do?

The React compiler transforms your React code into standard JavaScript. When enabled, it 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.

![react compiler](https://assets.cmssy.io/6ae4795c65113d877fc8d877/823fc27f-4813-49ef-a481-4905c7484134-a1dffcf0c9bc.png)

### 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 React Compiler on Idempotency

Enabling the React Compiler in a project 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 in most cases, as the compiler takes over the optimization process.

![memoization](https://assets.cmssy.io/6ae4795c65113d877fc8d877/e242142d-44e0-47fc-b747-ce0ebb5b0bbe-f4fbe00c366c.png)

Example of use performance hooks before React 19:

```tsx
import { useCallback, useMemo, useState } from "react";

function NameFilterApp() {
  const [names, setNames] = useState([
    "Tommy",
    "Arthur",
    "Polly",
    "John",
    "Grace",
  ]);
  const [filter, setFilter] = useState("");

  const handleFilterChange = useCallback((event) => {
    setFilter(event.target.value);
  }, []);

  const filteredNames = useMemo(
    () =>
      names.filter((name) => name.toLowerCase().includes(filter.toLowerCase())),
    [names, filter],
  );

  const totalLettersCount = useMemo(
    () => filteredNames.reduce((acc, name) => acc + name.length, 0),
    [filteredNames],
  );

  return (
    <>
      <input
        type="text"
        value={filter}
        onChange={handleFilterChange}
        placeholder="Filter names..."
      />
      <div>
        <strong>Filtered Names:</strong>
        {filteredNames.length > 0 ? filteredNames.join(", ") : "No results"}
      </div>
      <div>
        <strong>Total Number of Letters:</strong> {totalLettersCount}
      </div>
    </>
  );
}

export default NameFilterApp;
```

In this example:

1.  `useState` is used to track the current filter (`filter`) and the list of names (`names`).
2.  `useCallback` is utilized to optimize the function handling changes in the filter text field, to prevent unnecessary re-rendering.
3.  `useMemo` is 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 when `names` or `filter` changes, not on every render.

When enabled, the React Compiler optimizes your app code automatically, which makes most manual memoization unnecessary. New code can look like this (in existing code, test carefully before removing memoization):

```tsx
import { useState } from "react";

function NameFilterApp() {
  const [names, setNames] = useState([
    "Tommy",
    "Arthur",
    "Polly",
    "John",
    "Grace",
  ]);
  const [filter, setFilter] = useState("");

  const handleFilterChange = (event) => {
    setFilter(event.target.value);
  };

  const filteredNames = names.filter((name) =>
    name.toLowerCase().includes(filter.toLowerCase()),
  );

  const totalLettersCount = filteredNames.reduce(
    (acc, name) => acc + name.length,
    0,
  );

  return (
    <>
      <input
        type="text"
        value={filter}
        onChange={handleFilterChange}
        placeholder="Filter names..."
      />
      <div>
        <strong>Filtered Names:</strong>
        {filteredNames.length > 0 ? filteredNames.join(", ") : "No results"}
      </div>
      <div>
        <strong>Total Number of Letters:</strong> {totalLettersCount}
      </div>
    </>
  );
}

export default NameFilterApp;
```

* * *

In react 19 you also no more need to use forwardRef.

![component forwardRef](https://assets.cmssy.io/6ae4795c65113d877fc8d877/befa6810-1c31-4bf7-a498-323d568981f3-2dd36a993e0a.png)

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:

![component without forwardRef](https://assets.cmssy.io/6ae4795c65113d877fc8d877/33cb49c5-c3ad-4cb4-b486-c5c2871f4712-003b1a3781ae.png)

## 💪 Directives and Actions

![directives](https://assets.cmssy.io/6ae4795c65113d877fc8d877/86b1c00b-5817-40e3-88ab-5b6042dbd87d-faaf2a356b77.png)

### `'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
'use client';

import { useState } from 'react';

function InteractiveComponent() {
  const [count, setCount] = useState(0);

  return (
    <div>
      <p>{count}</p>
      <button onClick={() => setCount(count + 1)}>Increment</button>
    </div>
  );
}
```

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
'use client';

import { useEffect } from 'react';

function GeolocationComponent() {
  useEffect(() => {
    navigator.geolocation.getCurrentPosition(position => {
      console.log(position);
    });
  }, []);

  return <p>Check the console for the current position.</p>;
}
```

#### 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](https://react.dev/reference/react/use-client)

### `'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
// SignUpForm.js (Client Component)
import { useState } from 'react';

function SignUpForm({ submitEmail }) {
  const [email, setEmail] = useState('');

  const handleSubmit = async (e) => {
    e.preventDefault();
    await submitEmail({ email });
  };

  return (
    <form onSubmit={handleSubmit}>
      <input
        type="email"
        value={email}
        onChange={(e) => setEmail(e.target.value)}
      />
      <button type="submit">Sign Up</button>
    </form>
  );
}

// submitEmail.js (Server Action)
'use server';

export async function submitEmail({ email }) {
  // Logic to add email to database
}
```

#### 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](https://react.dev/reference/react/use-server)

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

![use() hook](https://assets.cmssy.io/6ae4795c65113d877fc8d877/2ba27233-6a6a-45eb-bd5c-7b8c4a7748d6-bdd5bd8e1373.png)

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
import { useEffect, useState } from "react";

const FetchDataComponent = () => {
  const [posts, setPosts] = useState([]);
  const [isLoading, setIsLoading] = useState(true);
  const [error, setError] = useState(null);

  useEffect(() => {
    const fetchData = async () => {
      try {
        const response = await fetch(
          "https://jsonplaceholder.typicode.com/posts",
        );
        if (!response.ok) {
          throw new Error("Data could not be fetched!");
        }
        const data = await response.json();
        setPosts(data);
      } catch (error) {
        setError(error.message);
      } finally {
        setIsLoading(false);
      }
    };

    fetchData();
  }, []);

  if (isLoading) {
    return <div>Loading...</div>;
  }

  if (error) {
    return <div>Error: {error}</div>;
  }

  return (
    <div>
      <h1>Test Posts</h1>
      <ul>
        {posts.map((post) => (
          <li key={post.id}>{post.title}</li>
        ))}
      </ul>
    </div>
  );
};

export default FetchDataComponent;
```

  
In this component, we perform the following steps:

1.  **State Definition**: We use the `useState` hook to create states for storing posts, the loading state (`isLoading`), and any potential errors (`error`).
2.  **Data Fetching**: We use the `useEffect` hook to perform an asynchronous `fetch` request to the API after the component has loaded. The `fetchData` function is asynchronous, allowing the use of `await` to wait for network responses.
3.  **State Management**: Depending on the network response, we update the state of the posts, loading, and error. We use `try...catch` to handle errors during the request.
4.  **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
// 1. Import React Hooks and Components
import { use, Suspense } from "react";

// 2. Define the Data Fetching Function
// This function fetches posts from a remote API and returns a promise.
const fetchPosts = () => {
  return fetch("https://jsonplaceholder.typicode.com/posts")
    .then((response) => {
      if (!response.ok) {
        throw new Error("Data could not be fetched!");
      }
      return response.json();
    });
};

// Cache the promise so the same instance is reused across re-renders.
// Creating it during render would start a new request and suspend again.
let postsPromise;
const getPosts = () => {
  postsPromise ??= fetchPosts();
  return postsPromise;
};

// Component that uses the `use` hook to fetch and display posts
const FetchDataComponent = () => {
  // 3. Use the `use` Hook to Fetch Data
  // The `use` hook is called with the cached promise returned by `getPosts`.
  const posts = use(getPosts());

  // 5. Map Over the Fetched Data
  // This renders a list of posts by mapping over the array of fetched posts.
  return (
    <div>
      <h1>Test Posts</h1>
      <ul>
        {posts.map((post) => (
          <li key={post.id}>{post.title}</li>
        ))}
      </ul>
    </div>
  );
};

// 6. Render the Component Tree
// The `App` component that renders the `FetchDataComponent` within a `Suspense` component.
export default function App() {
  return (
    // 4. Handle Loading State with `Suspense`
    // `Suspense` shows a fallback UI while the data is being fetched.
    <Suspense fallback={<div>Loading...</div>}>
      <FetchDataComponent />
    </Suspense>
  );
}
```

In this approach, using new `use()` hook we perform the following steps:

1.  **Import React Hooks and Components**: The code starts by importing the necessary hooks and components from React. This includes the `use` hook and the `Suspense` component.
2.  **Define the Data Fetching Function**: A function named `fetchPosts` is defined outside the React component. This function is responsible for fetching data from a remote API (`https://jsonplaceholder.typicode.com/posts`). It uses the `fetch` API to make a GET request and returns a promise that resolves with the data or rejects with an error. `getPosts` caches that promise so every render reuses the same instance.
3.  **Use the** **`use`** **Hook to Fetch Data**: Within the `FetchDataComponent`, the `use` hook is called with the cached promise returned by `getPosts`. The `use` hook reads the value of this promise. The promise must be cached: a promise created during render would start a new request and suspend again on every render. In a framework with Server Components, you can instead create the promise in a Server Component and pass it down as a prop.
4.  **Handle Loading State with** **`Suspense`**: The `FetchDataComponent` is wrapped in a `Suspense` component in the parent `App` component. The `Suspense` component 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 the `FetchDataComponent`'s UI, displaying the fetched data.
5.  **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.
6.  **Render the Component Tree**: Finally, the `App` component (containing the `Suspense` and `FetchDataComponent`) is rendered. When the `App` component 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
import React from 'react';
import { ThemeContext, ThemeComponent } from './Context';

// The main application component with a context provider
const App: React.FC = () => {
  return (
    <ThemeContext.Provider value="dark">
      <ThemeComponent />
    </ThemeContext.Provider>
  );
}

export default App;
```

```tsx
import React, { createContext, useContext, ReactNode } from 'react';

// Creating a Context with a default value of 'light'
export const ThemeContext = createContext<string>('light');

interface ThemeComponentProps {
  children?: ReactNode;
}

// Component using useContext
export const ThemeComponent: React.FC<ThemeComponentProps> = () => {
  const theme = useContext(ThemeContext);
  return <div>Current theme: {theme}</div>;
}
```

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
import React, { createContext, ReactNode, use } from 'react';

// Creating a Context with a default value of 'light'
export const ThemeContext = createContext<string>('light');

interface ThemeComponentProps {
  children?: ReactNode;
}

// Component using the new use() hook
export const ThemeComponent: React.FC<ThemeComponentProps> = () => {
  const theme = use(ThemeContext);
  return <div>Current theme: {theme}</div>;
}
```

#### Advantages of the `use` Hook

-   **Asynchronous Resource Loading:** Seamlessly load different resources asynchronously, improving performance and user experience.
-   **Simplifies Data Fetching:** With a cached promise or a Suspense-enabled framework, it can replace the `useEffect` hook in many data fetching tasks, offering a more straightforward approach to making API requests and handling responses.
-   **Context Data Access:** It can replace `useContext` for accessing context data, reducing boilerplate and simplifying context management.

#### Practical Applications

-   **Data Fetching:** The `use` hook 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:** Reads context like `useContext`, but can also be called in conditionals and loops. This makes it easier to consume context in components, further reducing the complexity of React applications.

[official documentation of use() hook](https://react.dev/reference/react/use)

### The `useFormStatus()` hook

![useFormStatus()](https://assets.cmssy.io/6ae4795c65113d877fc8d877/0b1fde8f-d0b2-4a9c-8297-ba11d285bf15-367d91666d71.png)

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
const { pending, data, method, action } = useFormStatus();
```

#### 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**: `useFormStatus` does 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. When `true`, 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 be `null` if 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 the `method` attribute of the form, defaulting to 'get' if unspecified.
    -   `action`: This refers to the function provided to the form's `action` prop. It will be `null` if the form is not wrapped by a parent `<form>`, if the `action` prop is set to a URI, or if no `action` prop is provided.

#### Important Considerations

-   **Form Dependency**: It's crucial to call `useFormStatus` from 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
import { useFormStatus } from "react-dom";
import { submitForm } from "./actions.js";

function Submit() {
  const { pending } = useFormStatus();
  return (
    <button type="submit" disabled={pending}>
      {pending ? "Submitting..." : "Submit"}
    </button>
  );
}

function Form({ action }) {
  return (
    <form action={action}>
      <Submit />
    </form>
  );
}

export default function App() {
  return <Form action={submitForm} />;
}
```

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 `useActionState()` hook

The `useActionState` 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 `useActionState` Offers

`useActionState` enables the creation of component state that updates in response to form actions. By passing an action function and an initial state to `useActionState`, you receive a new form action and the latest state, which can then be utilized within your form components.

#### How to Use `useActionState`

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
// actions.js
// Simulate a form submission that can either succeed or fail.
export async function submitForm(previousState, formData) {
  try {
    // Simulate checking formData for success or failure criteria.
    if (formData.get('exampleField') === 'success') {
      return { status: 'success', message: 'Form submitted successfully.' };
    } else {
      throw new Error('Form submission failed.');
    }
  } catch (error) {
    return { status: 'error', message: error.message };
  }
}
```

StatefulForm Component with Success and Error Feedback

```tsx
import React from 'react';
import { useActionState } from 'react';
import { submitForm } from './actions';

function StatefulForm() {
  const [state, formAction] = useActionState(submitForm, { status: 'idle', message: '' });

  return (
    <form action={formAction}>
      <input name="exampleField" placeholder="Type 'success' for success" />
      <button type="submit">Submit</button>

      {/* Feedback based on the form's submission state */}
      {state.status === 'success' && <p style={{ color: 'green' }}>{state.message}</p>}
      {state.status === 'error' && <p style={{ color: 'red' }}>{state.message}</p>}
    </form>
  );
}

export default StatefulForm;
```

#### Explanation of the Code

-   **Action Function (****`submitForm`****)**: This function simulates a form submission process. It returns a state object containing a `status` and a `message`. The `status` can either be `success` or `error`, determined by the submitted form data.
-   **Form Component (****`StatefulForm`****)**:
    -   Initializes form state using `useActionState`, with an initial state indicating that the form is idle.
    -   Renders a simple form with an input field and a submit button. `formAction` is passed to the form's `action` prop, so React calls it with the form's `FormData` inside a Transition.
    -   Displays feedback messages based on the form's submission state. Success messages are shown in green, while error messages are displayed in red.

This example showcases how `useActionState` can be utilized to manage form submission feedback dynamically, improving user experience by providing immediate and relevant responses to their actions.

### The `useOptimistic` hook

![useOptimistic() hook](https://assets.cmssy.io/6ae4795c65113d877fc8d877/42e79b9f-93f2-49fa-83d8-82b86df50bfd-9ee168d2dfcb.png)

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
import React, { useState } from 'react';
import { useOptimistic } from 'react';

function MessageSender() {
  const [messages, setMessages] = useState([]);
  const [messageInput, setMessageInput] = useState('');

  const [optimisticMessages, addOptimistic] = useOptimistic(messages, (currentMessages, optimisticMessage) => {
    // Merge the current messages with the optimistic update
    return [...currentMessages, optimisticMessage];
  });

  const sendMessage = async (message) => {
    addOptimistic({ id: Date.now(), text: message, status: 'Sending...' });
    try {
      // Simulate a network request to send the message
      await new Promise(resolve => setTimeout(resolve, 1000));
      // After the request completes, update the actual state
      setMessages(prev => [...prev, { id: Date.now(), text: message, status: 'Sent' }]);
    } catch (error) {
      console.error('Failed to send message:', error);
    }
  };

  const handleSubmit = (event) => {
    event.preventDefault();
    sendMessage(messageInput);
    setMessageInput('');
  };

  return (
    <div>
      <form onSubmit={handleSubmit}>
        <input 
          value={messageInput} 
          onChange={(e) => setMessageInput(e.target.value)} 
          placeholder="Type a message" 
        />
        <button type="submit">Send</button>
      </form>
      <ul>
        {optimisticMessages.map(msg => (
          <li key={msg.id}>{msg.text} - {msg.status}</li>
        ))}
      </ul>
    </div>
  );
}
```

#### Code Explanation

1.  **State Initialization**: The component maintains two state variables: `messages` for the actual messages and `messageInput` for the current input value.
2.  **Optimistic State**: `useOptimistic` is used to create an `optimisticMessages` state, which combines the actual messages with any optimistic updates.
3.  **Sending Messages**: The `sendMessage` function optimistically updates the UI using `addOptimistic`, immediately showing the message as "Sending...". It then simulates a network request and, upon completion, updates the `messages` state to reflect that the message has been sent.
4.  **UI Rendering**: The component renders an input form for messages and a list of messages. The list reflects the `optimisticMessages` state, 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

![new form hooks](https://assets.cmssy.io/6ae4795c65113d877fc8d877/81530de9-a5f0-4612-b516-53b5d784f17d-react-19-form-hooks-useactionstate.png)

## Summary

React 19 introduces a suite of features and improvements designed to enhance developer experience and application performance. Alongside it, the separately released React Compiler 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**: A separate build-time tool, released independently of 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()`, and `memo()`.
-   **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 brings stable support for Server Components, using the `'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, `useActionState` for form state based on action results, and `useOptimistic` for 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!