DEV Community

Cover image for Amazing React 19 Updates 🔥🔥😍...
Srijan Baniyal
Srijan Baniyal

Posted on

Amazing React 19 Updates 🔥🔥😍...

ReactJS stands out as a leading UI library in the front-end development sphere, and my admiration for it is fueled by the dedicated team and the vibrant community that continually supports its growth.

The prospects for React are filled with promise and intrigue. To distill it into a single line, one could simply state: 'Minimize Code, Maximize Functionality'.

Throughout this blog, I aim to delve into the fresh elements introduced in React 19, enabling you to delve into new functionalities and grasp the evolving landscape.

Please bear in mind that React 19 is currently undergoing development. Please Remember to refer the official guide on GitHub and follow the official team on social platforms to remain abreast of the most recent advancements.


1.Overview of New Features in React 19
2.React Compiler
3.Server Components
4.Actions
5.Document Metadata
6.Asset Loading
7.Web Components
8.New react Hooks
9.Wanna Try Out React 19 🤔??


✨Overview of New Features in React 19✨

Here's a brief rundown of the exciting new features that React 19 is set to bring:

  • 🎨 React Compiler Breakthrough: React enthusiasts are eagerly anticipating the arrival of a cutting-edge compiler. Already in use by Instagram, this technology will soon be integrated into future React versions.
  • 🚀 Server Component Innovation: After years of development, React is unveiling server components, a groundbreaking advancement compatible with Next.js.
  • 🔬 Revolutionary DOM Interactions AKA Actions: Brace yourself for the game-changing impact of the new Actions feature on how we engage with DOM elements.
  • 📝 Streamlined Document Metadata: Expect a significant upgrade in enhancing developers' efficiency with a leaner code approach.
  • 🖼️ Efficient Assets Loading: Say goodbye to tedious loading times as React's new asset loading capability enhances both app load times and user experiences.
  • ⚙️ Web Component Integration: Excitingly, React code will seamlessly incorporate web components, opening up a world of possibilities for developers.
  • 🪝 Enhanced Hooks Ecosystem: Anticipate a wave of cutting-edge hooks coming your way soon, poised to transform the coding landscape.

React 19 will address the persistent challenge of excessive re-renders in React development, enhancing performance by autonomously managing re-renders. This marks a shift from the manual use of useMemo(), useCallback(), and memo, resulting in cleaner and more efficient code and streamlining the development process.


🎨React Compiler🎨

One common approach to optimizing these re-renders has been the manual use of useMemo(), useCallback(), and memo APIs. The React team initially considered this a "reasonable manual compromise" in their effort to delegate the management of re-renders to React.

Recognizing the cumbersome nature of manual optimization and buoyed by community feedback, the React team set out to address this challenge. Hence, they introduced the "React compiler", which takes on the responsibility of managing re-renders. This empowers React to autonomously determine the appropriate methods and timing for updating state and refreshing the UI.

As a result, developers are no longer required to perform these tasks manually, and the need for useMemo(), useCallback(), and memo is alleviated.

As this functionality is set to be included in a future release of React, you can delve deeper into the details of the compiler by exploring the following sources:

React Compiler: In-Depth by Jack Herrington

React Official Documentation

Consequently, React will autonomously determine the optimization of components and the timing for the same, as well as make decisions on what needs to be re-rendered.


🚀Server Components🚀

If you're not aware of server components, you're overlooking a remarkable Landmark of advancement in React and Next.js.

Historically, React components predominantly operated on the client side. However, React is now disrupting the status quo by introducing the innovative notion of server-side component execution.

The concept of server components has been a topic of discussion for years, with Next.js leading the charge by incorporating them into production. Beginning with Next.js 13, all components are automatically designated as server components. To execute a component on the client side, you must employ the "use client" directive.

In React 19, the integration of server components within React presents
a multitude of benefits:

  • Enhanced SEO: Server-rendered components elevate search engine optimization efforts by offering crawler-friendly content.
  • Performance Enhancement: Server components play a pivotal role in accelerating initial page load times and enhancing performance, especially for content-rich applications.
  • Server-Side Functionality: Leveraging server components facilitates the execution of code on the server side, streamlining processes such as API interactions for optimal efficiency.

These advantages highlight the profound impact server components can have on advancing contemporary web development practices.

In React, components are inherently designed for client-side execution. However, by employing the "use server" directive as the initial line of a component, the code can be transformed into a server component. This adjustment ensures that the component operates exclusively on the server side and will not be executed on the client side.


🔬Actions🔬

In the upcoming version 19, the introduction of Actions promises to revolutionize form handling. This feature will enable seamless integration of actions with the <form/> HTML tag, essentially replacing the traditional onSubmit event with HTML form attributes.

Before Actions

<form onSubmit={search}>
  <input name="query" />
  <button type="submit">Search</button>
</form>
Enter fullscreen mode Exit fullscreen mode

After Actions

With the debut of server components, Actions now have the capability to be executed on the server side. Within our JSX, through the tag, we can go for the onSubmitevent and instead incorporate the action attribute. This attribute will encompass a method for submitting data, whether it be on the client or server side.
Actions empower the execution of both synchronous and asynchronous operations, simplifying data submission management and state updates. The primary objective is to streamline form handling and data manipulation, seeking to enhance overall user experience.

Shall we explore an example to gain a better understanding of this functionality?

"use server"

const submitData = async (userData) => {
    const newUser = {
        username: userData.get('username'),
        email: userData.get('email')
    }
    console.log(newUser)
}

Enter fullscreen mode Exit fullscreen mode
const Form = () => {
    return <form action={submitData}>
        <div>
            <label>Name</label>
            <input type="text" name='username'/>
        </div>
        <div>
            <label>Name</label>
            <input type="text" name="email" />
        </div>
        <button type='submit'>Submit</button>
    </form>
}

export default Form;
Enter fullscreen mode Exit fullscreen mode

In the provided code snippet, submitData functions as the action within the server component, while form serves as the client-side component utilizing submitData as the designated action. Significantly, submitData will execute exclusively on the server side. This seamless communication between the client (form) and server (submitData) components is facilitated solely through the action attribute.


📝Document Metadata📝

The inclusion of elements like title, meta tags and description is essential for maximizing SEO impact and ensuring accessibility. Within the React environment, especially prevalent in single-page applications, the task of coordinating these elements across different routes can present a significant hurdle.

Typically, developers resort to crafting intricate custom solutions or leveraging external libraries like react-helmet to orchestrate seamless route transitions and dynamically update metadata. Yet, this process can become tedious and error-prone, particularly when handling crucial SEO elements such as meta tags.

Before:

import React, { useEffect } from 'react';

const HeadDocument = ({ title }) => {
  useEffect(() => {
    document.title = title;

    const metaDescriptionTag = document.querySelector('meta[name="description"]');
    if (metaDescriptionTag) {
    metaDescriptionTag.setAttribute('content', 'New description');
    }
  }, [title]);

  return null;
};

export default HeadDocument;
Enter fullscreen mode Exit fullscreen mode

The provided code features a HeadDocument component tasked with dynamically updating the title and meta tags based on the given props within the useEffect hook. This involves utilizing JavaScript to facilitate these updates, ensuring that the component is refreshed upon route changes. However, this methodology may not be considered the most elegant solution for addressing this requirement.

After:

Through React 19, we have the ability to directly incorporate title and meta tags within our React components:

Const HomePage = () => {
  return (
    <>
      <title>Freecodecamp</title>
      <meta name="description" content="Freecode camp blogs" />
      // Page content
    </>
  );
}
Enter fullscreen mode Exit fullscreen mode

This was not possible before in React. The only way was to use a package like react-helmet.


🖼️Asset Loading🖼️

In React, optimizing the loading experience and performance of applications, especially with images and asset files, is crucial.

Traditionally, there can be a flicker from unstyled to styled content as the view loads items like stylesheets, fonts, and images. Developers often implement custom solutions to ensure all assets are loaded before displaying the view.

In React 19, images and files will load in the background as users navigate the current page, reducing waiting times and enhancing page load speed. The introduction of lifecycle Suspense for asset loading, including scripts and fonts, allows React to determine when content is ready to prevent any unstyled flickering.

New Resource Loading APIs like preload and preinit offer increased control over when resources load and initialize. With assets loading asynchronously in the background, React 19 optimizes performance, providing a seamless and uninterrupted user experience.


⚙️Web Components⚙️

Two years ago, I ventured into the realm of web components and became enamored with their potential. Let me provide you with an overview:

Web components empower you to craft custom components using native HTML, CSS, and JavaScript, seamlessly integrating them into your web applications as if they were standard HTML tags. Isn't that remarkable?

Presently, integrating web components into React poses challenges. Typically, you either need to convert the web component to a React component or employ additional packages and code to make them compatible with React. This can be quite frustrating.

However, the advent of React 19 brings promising news for integrating web components into React with greater ease. This means that if you encounter a highly valuable web component, such as a carousel, you can seamlessly incorporate it into your React projects without the need for conversion into React code.

This advancement streamlines development and empowers you to harness the extensive ecosystem of existing web components within your React applications.

While specific implementation details are not yet available, I am optimistic that it may involve simply importing a web component into a React codebase, akin to module federation. I eagerly anticipate further insights from the React team on this integration.

🪝New React Hooks🪝

React Hooks have solidified their place as a beloved feature within the React library. Chances are you've embraced React's standard hooks frequently and maybe even ventured into creating your unique custom hooks. These hooks have gained such widespread acclaim that they have evolved into a prevalent programming methodology within the React community.

With the upcoming release of React 19, the utilization of useMemo, forwardRef, useEffect and useContext is poised for transformation. This shift is primarily driven by the impending introduction of a novel hook, named use.

useMemo():

You won't need to use the useMemo() hook after React19, as React Compiler will memoize by itself.

Before:

import React, { useState, useMemo } from 'react';

function ExampleComponent() {
  const [inputValue, setInputValue] = useState('');

  // Memoize the result of checking if the input value is empty
  const isInputEmpty = useMemo(() => {
    console.log('Checking if input is empty...');
    return inputValue.trim() === '';
  }, [inputValue]);

  return (
    <div>
      <input
        type="text"
        value={inputValue}
        onChange={(e) => setInputValue(e.target.value)}
        placeholder="Type something..."
      />
      <p>{isInputEmpty ? 'Input is empty' : 'Input is not empty'}</p>
    </div>
  );
}

export default ExampleComponent;
Enter fullscreen mode Exit fullscreen mode

After:

In the below example, you can see that after React19, we don't need to memo the values – React19 will do it by itself under the hood. The code is much cleaner:

import React, { useState, useMemo } from 'react';

function ExampleComponent() {
  const [inputValue, setInputValue] = useState('');

  const isInputEmpty = () => {
    console.log('Checking if input is empty...');
    return inputValue.trim() === '';
  });

  return (
    <div>
      <input
        type="text"
        value={inputValue}
        onChange={(e) => setInputValue(e.target.value)}
        placeholder="Type something..."
      />
      <p>{isInputEmpty ? 'Input is empty' : 'Input is not empty'}</p>
    </div>
  );
}

export default ExampleComponent;
Enter fullscreen mode Exit fullscreen mode

forwardRef():

ref will be now passed as props rather than using the forwardRef() hook. This will simplify the code. So after React 19, you won't need to use forwardRef().

Before:

import React, { forwardRef } from 'react';

const ExampleButton = forwardRef((props, ref) => (
  <button ref={ref}>
    {props.children}
  </button>
));
Enter fullscreen mode Exit fullscreen mode

After:

ref can be passed as a "prop". No more forwardRef() is required.

import React from 'react';

const ExampleButton = ({ ref, children }) => (
  <button ref={ref}>
    {children}
  </button>
);
Enter fullscreen mode Exit fullscreen mode

The new use() hook

React 19 will introduce a new hook called use(). This hook will simplify how we use promises, async code, and context.

Here is the syntax of hook:

const value = use(resource);
Enter fullscreen mode Exit fullscreen mode

The below code is an example of how you can use the use() hook to make a fetch request:

import { use } from "react";

const fetchUsers = async () => {
    const res = await fetch('https://jsonplaceholder.typicode.com/users');
    return res.json();
  };

  const UsersItems = () => {
    const users = use(fetchUsers());

    return (
      <ul>
        {users.map((user) => (
          <div key={user.id} className='bg-blue-50 shadow-md p-4 my-6 rounded-lg'>
            <h2 className='text-xl font-bold'>{user.name}</h2>
            <p>{user.email}</p>
          </div>
        ))}
      </ul>
    );
  }; 
export default UsersItems;
Enter fullscreen mode Exit fullscreen mode

Let's understand the code:

  1. The function fetchUsers handles the GET request operation.
  2. Instead of employing the useEffect or useState hooks, we utilize the use hook to execute fetchUsers.
  3. The outcome of the useState hook, referred to as users, stores the response obtained from the GET request (users).
  4. Within the return section, we leverage users to iterate through and construct the list.

Another area where the new hook can be utilized is with Context. The Context API is widely adopted for global state management in React, eliminating the need for external state management libraries. With the introduction of the use hook, the context hook will be represented as follows:

Instead of employing useContext(), we will now utilize use(context).

import { createContext, useState, use } from 'react';

const ThemeContext = createContext();

const ThemeProvider = ({ children }) => {
  const [theme, setTheme] = useState('light');

  const toggleTheme = () => {
    setTheme((prevTheme) => (prevTheme === 'light' ? 'dark' : 'light'));
  };

  return (
    <ThemeContext.Provider value={{ theme, toggleTheme }}>
      {children}
    </ThemeContext.Provider>
  );
};

const Card = () => {
  // use Hook()
  const { theme, toggleTheme } = use(ThemeContext);

  return (
    <div
      className={`p-4 rounded-md ${
        theme === 'light' ? 'bg-white' : 'bg-gray-800'
      }`}
    >
      <h1
        className={`my-4 text-xl ${
          theme === 'light' ? 'text-gray-800' : 'text-white'
        }`}
      >
        Theme Card
      </h1>
      <p className={theme === 'light' ? 'text-gray-800' : 'text-white'}>
       Hello!! use() hook
      </p>
      <button
        onClick={toggleTheme}
        className='bg-blue-500 hover:bg-blue-600 text-white rounded-md mt-4 p-4'
      >
        {theme === 'light' ? 'Switch to Dark Mode' : 'Switch to Light Mode'}
      </button>
    </div>
  );
};

const Theme = () => {
  return (
    <ThemeProvider>
      <Card />
    </ThemeProvider>
  );
};

export default Theme
Enter fullscreen mode Exit fullscreen mode

The component ThemeProvider is responsible for providing the context, while the component card is where we will consume the context using the new hook, use. The remaining structure of the code remains unchanged from before React 19.

The useFormStatus() hook:

The new hook introduced in React 19 will provide enhanced control over the forms you develop, offering status updates regarding the most recent form submission.

Syntax:

const {pending, action , data , method } = useFormStatus()

Or the Simpler version

const {status} = useFormStatus()

This hook provides the following information:

1."pending": Indicates if the form is currently in a pending state, yielding true if so, and false otherwise.
2."data": Represents an object conforming to the FormData interface, encapsulating the data being submitted by the parent.
3."method": Denotes the HTTP method, defaulting to GET unless specified otherwise.
4."action": A reference to an Action

This hook serves the purpose of displaying the pending state and the data being submitted by the user.

import { useFormStatus } from "react-dom";

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

const formAction = async () => {
  // Simulate a delay of 2 seconds
  await new Promise((resolve) => setTimeout(resolve, 3000));
}

const FormStatus = () => {
  return (
    <form action={formAction}>
      <Submit />
    </form>
  );
};

export default FormStatus;
Enter fullscreen mode Exit fullscreen mode

In the provided code snippet:

  • The Submit method serves as the action to submit the form. It utilizes the status retrieved from useFormStatus to determine the value of status.pending.
  • This status.pending value is used to dynamically display messages on the UI based on its true or false state.
  • The formAction method, a fake method, is employed to simulate a delay in form submission.

Through this implementation, upon form submission, the useFormStatus hook tracks the pending status. While the status is pending (true), the UI displays "Submitting..."; once the pending state transitions to false, the message adjusts to "Submitted".

This hook proves to be robust and beneficial for monitoring form submission status and facilitating appropriate data display based on the status.

The useFormState() hook

Another new hook in the React 19 is UseFormState(). It allows you to update state based on the result of form submission.

Syntax:

const [state,formaction] = UseFormState(fn,initialState,permalink?);

1.fn: The function to be called when the form is submitted or the button is pressed.
2.initalstate: The value you want the state to be initially. It can be any serialized value. This argument is ignored after the action is first ignored after the action is first invoked.
3.permalink: This is optional. A URL or page link, if fn is going to be run on the server then the page will redirect to permalink.

This hook will return:

  1. state: The initial state will be the value we have passed to initialState.
  2. formAction: An action that will be passed to the form action. the Return value of this will be available in the state.
import { useFormState} from 'react-dom';

const FormState = () => {
    const submitForm = (prevState, queryData) => {
        const name =  queryData.get("username");
        console.log(prevState); // previous form state
        if(name === "Srijan"){
            return {
                success: true,
                text: "Welcome"
            }
        }
        else{
            return {
                success: false,
                text: "Error"
            }
        }
    }
    const [ message, formAction ] = useFormState(submitForm, null)
    return <form action={formAction}>
        <label>Name</label>
        <input type="text" name="username" />
        <button>Submit</button>
        {message && <h1>{message.text}</h1>}
    </form>
}

export default FormState;
Enter fullscreen mode Exit fullscreen mode

Understanding the Code given above:

1.submitForm is the method responsible for the form submission. This is the Action {remember Action is new feature in React 19}.

2.Inside submitForm, we are checking the value of the form. Then, depending on whether it's successful or shows an error, we return the specific value and message. In the above code example , if there is any value other than "Srijan", then it will return an error.
3.We can also check the pervState of the form. The initial state would be null, and after that it will return the prevState of the form.

On running this example, you will see a "welcome" message if the name is Srijan - otherwise it will return "error".

The useOptimistic() hook :

useOptimistic is a React Hook that lets you show a different state while a sync action is underway, according to the React docs.

This hook will help enhance the user experiences and should result in faster responses. This will be useful for application that need to interact with the server.

Syntax:

const [optimisticMessage,addOptimisticMessage] = useOptimistic(state,updatefn)

For instance, when a response is being processed, an immediate "state" can be displayed to provide the user with prompt feedback. Once the actual response is received from the server, the "optimistic" state will be replaced by the authentic result.

The useOptimistic hook facilitates an immediate update of the UI under the assumption that the request will succeed. This naming reflects the "optimistic" presentation of a successful action to the user, despite the actual action taking time to complete.

Now, let's explore how we can incorporate the useOptimistic hook. The code below showcases the display of an optimistic state upon clicking the submit button in a (e.g., "Sending..."), persisting until the response is received.

import { useOptimistic, useState } from "react";

const Optimistic = () => {
  const [messages, setMessages] = useState([
    { text: "Hey, I am initial!", sending: false, key: 1 },
  ]);
  const [optimisticMessages, addOptimisticMessage] = useOptimistic(
    messages,
    (state, newMessage) => [
      ...state,
      {
        text: newMessage,
        sending: true,
      },
    ]
  );

  async function sendFormData(formData) {
    const sentMessage = await fakeDelayAction(formData.get("message"));
    setMessages((messages) => [...messages, { text: sentMessage }]);
  }

  async function fakeDelayAction(message) {
    await new Promise((res) => setTimeout(res, 1000));
    return message;
  }

  const submitData = async (userData) => {
    addOptimisticMessage(userData.get("username"));

    await sendFormData(userData);
  };

  return (
    <>
      {optimisticMessages.map((message, index) => (
        <div key={index}>
          {message.text}
          {!!message.sending && <small> (Sending...)</small>}
        </div>
      ))}
      <form action={submitData}>
        <h1>OptimisticState Hook</h1>
        <div>
          <label>Username</label>
          <input type="text" name="username" />
        </div>
        <button type="submit">Submit</button>
      </form>
    </>
  );
};

export default Optimistic;
Enter fullscreen mode Exit fullscreen mode
  1. The method fakeDelayAction serves as a simulated delay mechanism to mimic the submit event delay, showcasing the optimistic state conceptually. 2.submitData acts as the action responsible for submitting the form. It can potentially include asynchronous operations as well.
  2. sendFormData is tasked with transmitting the form data to fakeDelayAction for processing. 4.Initialize the default state where the messages attribute is designated for input within the useOptimistic() function, ultimately returned as optimisticMessages.

const [messages, setMessages] = useState([{ text: "Hey, I am initial!", sending: false, key: 1 },]);

Now , let's get into more details:

Inside submitData , we are using addOptimisticMessage.This will add the form data so that it will be available in optimisticMessage. We will use this to show a message in the UI:

{optimisticMessages.map((message, index) => (
        <div key={index}>
          {message.text}
          {!!message.sending && <small> (Sending...)</small>}
        </div>
      ))}
Enter fullscreen mode Exit fullscreen mode

Wanna Try Out React 19 🤔 ?

Presently, the aforementioned features are accessible in the canary release. Further information can be found here. As advised by the React team, refrain from using these features for customer or user-facing applications at this time. You are welcome to explore and experiment with them for personal learning or recreational purposes.

If you're eager to know the release date of React 19, you can stay informed by monitoring the Canary Releases for updates. Keep abreast of the latest developments by following the React team on their official website, team channels, GitHub and Canary Releases.

Top comments (0)