React JS 19 is coming soon with exciting updates ✨

Apr 27, 2024

cutting-edgereact-js

React is evolving and some exciting updates are coming up by the end of 2024. These updates are aimed at making it easier for developers to use this powerful library. Let's explore what's in store! âš¡

Let's see what we've got in store, shall we?

  1. Say goodbye to some Hooks and HOCs! With the new React Compiler, you won't need to worry about using useMemo, useCallback, or memo anymore. This new feature will do all the hard work for you! It's pretty smart too, as it will optimize your components by caching computations and memoizing callbacks without you having to do anything manually.
  2. Simplified Refs: Passing ref will become as easy as passing a prop. The forwardRef API will be set aside, reducing boilerplate and making component APIs more predictable and easier to understand.
  3. New Patterns Over React.lazy: Server Components (RSC) and new patterns like promise-as-a-child will replace React.lazy for code splitting and component loading, offering more efficient ways to dynamically load components based on user interactions and network conditions.
  4. Context and Suspense Changes: The useContext hook transforms into use(Context), embedding context consumption directly into the use hook for a more unified hooks API. Additionally, throwing promises in components for Suspense will be replaced with use(promise), standardizing asynchronous data fetching with the rest of the hooks ecosystem.
  5. Streamlined Context Providers: Creating context will be more straightforward without the .Provider component. You'll be able to use directly, which simplifies context creation and provides a more elegant syntax.

Andrew Clark @reactjs core team, @nextjs, @vercel

Overview of React 19's New Features


React Compiler: A Game Changer

The new React compiler is a standout feature. It automates re-rendering processes, allowing developers to focus more on crafting unique user experiences rather than optimizing performance manually. This innovation is already in action at Instagram, setting a precedent for its effectiveness in real-world applications.
// Before React 19
import React, { useState, useCallback } from 'react';

function Counter() {
  const [count, setCount] = useState(0);
  const increment = useCallback(() => {
    setCount(c => c + 1);
  }, []);

  return <button onClick={increment}>Count: {count}</button>;
}

// With React 19 Compiler
import React, { useState } from 'react';

function Counter() {
  const [count, setCount] = useState(0);
  const increment = () => setCount(c => c + 1);

  return <button onClick={increment}>Count: {count}</button>;
}
💡  The manual optimization using useCallback is no longer necessary.

Server Components

React 19 now allows server components to be integrated directly which can lead to SEO improvements and better performance by rendering components on the server-side. This integration is especially powerful when combined with frameworks like Next.js, offering a seamless experience from server to client
// This React 19 feature enables components to run on the server, enhancing performance and SEO.
'use server';

export default async function getUsername(userId) {
  const response = await fetch(`/api/users/${userId}`);
  const data = await response.json();
  return data.username;
}

Server Actions

The introduction of Actions transforms how forms interact within React applications. By binding Actions directly to form elements, React 19 allows for server-side executions, thereby enhancing the responsiveness and interactivity of web applications.
async function handleLogin(formData: FormData): Promise<void> {
  'use server';
  const username = formData.get('username');
  const password = formData.get('password');
  console.log(username, password)
  // this is where you would send the data to the server, it would be part of the server action folder/file
}

export default async function LoginForm() {
  return (
    <form action={handleLogin}>
      <input name="username" type="text" placeholder="Username" />
      <input name="password" type="password" placeholder="Password" />
      <button type="submit">Log In</button>
    </form>
  );
}

Async Transitions

React 19 introduces a new pattern for handling data mutations and state updates, which is especially beneficial when handling form submissions or any sequence that involves a user interaction that updates data. The new useTransition hook and action framework simplify the handling of asynchronous updates, enabling cleaner and more efficient state management.

// Example using useTransition for better state management in React 19
function UpdateName({}) {
  const [name, setName] = useState("");
  const [error, setError] = useState(null);
  const [isPending, startTransition] = useTransition();

  const handleSubmit = async () => {
    startTransition(async () => {
      const error = await updateName(name);
      if (error) {
        setError(error);
        return;
      }
      redirect("/path");
    });
  };

  return (
    <div>
      <input value={name} onChange={(event) => setName(event.target.value)} />
      <button onClick={handleSubmit} disabled={isPending}>Update</button>
      {error && <p>{error}</p>}
    </div>
  );
}
The async transition will instantly set the isPending state to true, execute the async request(s), and change isPending to false after all transitions. This ensures the UI remains responsive and interactive during data updates.

Simplifying Form Handling with Form Actions

React 19 further simplifies form handling by permitting direct passing of functions to the action and formAction props.

// Example using <form> Actions in React 19
function ChangeName({ name, setName }) {
  const [error, submitAction, isPending] = useActionState(
    async (previousState, formData) => {
      const error = await updateName(formData.get("name"));
      if (error) {
        return error;
      }
      redirect("/path");
    }
  );

  return (
    <form action={submitAction}>
      <input type="text" name="name" />
      <button type="submit" disabled={isPending}>Update</button>
      {error && <p>{error}</p>}
    </form>
  );
}
So, React 19 is bringing in some cool stuff. It's got this new thing called useOptmistic that helps manage optimistic updates. They've also introduced a new hook called useActionState which is pretty handy for Actions. Over in react-dom, they've added Form Actions that automatically manage forms, and useFormStatus for the common cases with Actions in forms.

NEW HOOKS 💡 ⚡

  • useActionState: Simplifies the management of action states in applications, especially when dealing with forms.
  • useFormStatus: Provides easy access to the status of forms, helping manage UI changes based on form state.
  • useOptimistic: Allows developers to implement optimistic UI updates, showing changes instantaneously while the data mutation is processed in the background.

Example using useActionState:

const [error, submitAction, isPending] = useActionState(async (previousState, newName) => {
  const error = await updateName(newName);
  if (error) {
    // You can return any result of the action.
    // Here, we return only the error.
    return error;
  }
  
  // handle success
});

Example using useFormStatus:

import {useFormStatus} from 'react-dom';

function DesignButton() {
  const {pending} = useFormStatus();
  return <button type="submit" disabled={pending} />
}

Example using useOptmistic:

function ChangeName({ currentName, onUpdateName }) {
  const [optimisticName, setOptimisticName] = useOptimistic(currentName);

  const submitAction = async formData => {
    const newName = formData.get("name");
    setOptimisticName(newName); // Optimistically update UI
    const updatedName = await updateName(newName);
    onUpdateName(updatedName); // Update with actual response
  };

  return (
    <form action={submitAction}>
      <p>Your name is: {optimisticName}</p>
      <input type="text" name="name" />
    </form>
  );
}

And here's the biggie we've all been waiting for: New API: use 💜

In React 19, a new API is introduced for reading resources during rendering: use. For example, you can utilize use to read a promise. React will suspend until the promise is resolved.

import {use} from 'react';

function Comments({commentsPromise}) {
  // `use` will suspend until the promise resolves.
  const comments = use(commentsPromise);
  return comments.map(comment => <p key={comment.id}>{comment}</p>);
}

function Page({commentsPromise}) {
  // When `use` suspends in Comments,
  // this Suspense boundary will be shown.
  return (
    <Suspense fallback={<div>Loading...</div>}>
      <Comments commentsPromise={commentsPromise} />
    </Suspense>
  )
}

Awesome! But let's see this in action, shall we? Check out the example I'm dropping below comparing useEffect and use.

Here’s an example using the traditional useEffect hook to fetch data:

import { useEffect, useState } from "react";

const JokeItem = ({ joke }) => {
  return (
    <div className="bg-blue-50 shadow-md p-4 my-6 rounded-lg">
      <h2 className="text-xl font-bold">{joke.value}</h2>
    </div>
  );
};

const Joke = () => {
  const [joke, setJoke] = useState([]);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    const fetchJoke = async () => {
      try {
        const res = await fetch("https://api.chucknorris.io/jokes/random");
        const data = await res.json();
        setJoke(data);
        setLoading(false);
      } catch (error) {
        console.error(error);
      } finally {
        setLoading(false);
      }
    };

    fetchJoke();
  }, []);

  if (loading) {
    return <h2 className="text-2xl text-center font-bold mt-5">Loading...</h2>;
  }

  return <JokeItem joke={joke} />;
};

export default Joke;

In the version we got here, useEffect is like the stage manager, handling all the setup and teardown for fetching our data. And we're taking care of loading and joke state ourselves, old school style.

Now, let’s see how the new use function simplifies the same operation:

import { use, Suspense } from "react";

const fetchData = async () => {
  const res = await fetch("https://api.chucknorris.io/jokes/random");
  return res.json();
};

const JokeItem = () => {
  const joke = use(fetchData());
  return (
    <div className="bg-blue-50 shadow-md p-4 my-6 rounded-lg">
      <h2 className="text-xl font-bold">{joke.value}</h2>
    </div>
  );
};

const Joke = () => {
  return (
    <Suspense
      fallback={
        <h2 className="text-2xl text-center font-bold mt-5">Loading...</h2>
      }
    >
      <JokeItem />
    </Suspense>
  );
};

export { Joke as UseExample1 };

So, what happens here is, use directly handles the promise returned by fetchData, suspending the component’s rendering until the data is available. React’s Suspense component then takes care of displaying a fallback UI during the loading state. The cool thing is, this way gets rid of the boring repetitive stuff, no need to manually manage any loading state and simplifying error handling.

Key Takeaways

  • Simplicity: The use API allows developers to write less code and manage fewer states manually, focusing more on the core functionality of components.
  • Declarative: With use, components declare what data they need, not how or when to fetch it, aligning with React’s overall declarative approach.
  • Efficiency: Suspense integrates seamlessly with use, improving handling of asynchronous data fetching by optimizing rendering and reducing the impact on the UI responsiveness.

Hope it was help full, and lets keep learning That's just a sneak peek of all the awesome features on the horizon! If you're keen to stay in the loop, make sure to check out the React Blog regularly, or better yet, keep an eye on my blog for the latest updates and insights. Hope you found this helpful—let's keep the learning journey going! 💜 ⚡

Summary

React 19 is poised to significantly enhance the efficiency, performance, and simplicity of developing React applications. From its new compiler to improved hooks and server-side components, React 19 encourages a more streamlined, performance-oriented approach to building modern web applications.

Key Takeaways

© 2025 Erick Eduardo. All rights reserved.