React 19: Latest Features and Updates

React 19: Latest Features and Updates

React—widely known as React.JS—is a JavaScript library open-sourced by Meta (formerly Facebook), maintained and developed by a core team. It is mainly used to create single-page applications. ReactJS is one of the most popular UI libraries for front-end development. React has been adopted more by other users because of its performance and simplicity, as well as for its efficiency

React 19 release will be an extraordinary moment of evolution for the library, featuring various improvements that make the development workflow smoother.

In this article, I will share what's new in React 19 so you can start experimenting with some of the features and learn about what's changing.

React 19: New features

  • React Compiler: The new React compiler (React Forget) is set to tackle one of React's longstanding challenges: the issue of excessive re-rendering. Previously, developers relied on manual techniques like useMemo(), useCallback() and memo to manage re-rendering and optimizations, React 19 will not require this type of manual intervention anymore.

    The compiler will intelligently identify and memoize code under the hood, resulting in cleaner and more efficient code. The new compiler is in the works, and is already being used by Instagram.

// Before React 19

function VideoTab ({videos, title}) {
    const uniqueVideos = useMemo(() => {
        return new Set(videos)
    }, [videos]);

    const size = uniqueVideos.size;

    return (
    <>
        <Heading title={title} size={size} />
        <VideoList videos={videos} /> 
    </>
    )
}

// With React 19

function VideoTab ({videos, title}) {
    const uniqueVideos =  new Set(videos);
    const size = uniqueVideos.size;

    return (
    <>
        <Heading title={title} size={size} />
        <VideoList videos={videos} /> 
    </>
    )
}
  • React Server components (RSC): React components have mostly operated on the client side up until now. However, the revolutionary idea of executing components on the server side is being introduced by React.

    Although the concept of server components has been around for a while, Next.js was the first to use them in a production setting. As of Next.js 13, by default, every component is a server component. The use client directive must be used in order to enable client-side operation for a component.

    All the components in React by default are client side. Only when you use use server will the component be a server component.

    Server components will be natively integrated into React with React 19, which has several benefits like SEO, Performance Boost, and Server-Side Execution.

  • Actions: A new feature in React 19 called Actions makes handling data changes and state modifications in your React apps easier. It does away with the necessity for manual coding to handle errors, optimistic updates, sequential requests, and pending states.

// Before React 19

function UpdateName({}) {
  const [name, setName] = useState("");
  const [error, setError] = useState(null);
  const [isPending, setIsPending] = useState(false);

  const handleSubmit = async () => {
    setIsPending(true);
    const error = await updateName(name);
    setIsPending(false);
    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>
  );
}

// With 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 null;
    },
    null,
  );

  return (
    <form action={submitAction}>
      <input type="text" name="name" />
      <button type="submit" disabled={isPending}>Update</button>
      {error && <p>{error}</p>}
    </form>
  );
}
  • Asset Loading: React 19 introduces asset loading, which allows assets to load in the background. This enhances the user experience and speeds up the application's load time. It's a substantial improvement because it gives you more control over when and how assets load, which can really affect speed.

    Additionally, lifecycle Suspense—which allows assets like scripts, stylesheets, and fonts to load—is being introduced by React. This feature removes any "unstyled" flickering by allowing React to decide when the content is ready to be displayed.

  • Web Components: Web Components in React 19 are much more compatible with the Web Components standard now. This allows for more flexible and compatible frontend development. This is cool because we can now use custom elements, shadow DOM, and HTML templates.

  • Document Metadata: React 19 now supports Document Metadata, whereby we can do way more with very few lines of code. It permits an individual to work with head elements like the title, meta tags, and other head elements within a document. This will be of help for SEO and user experience to find a way to change metadata at any time while responding to the state of the application.

  • New React Hooks: React Introduces four new hooks: useOptimistic, useFormStatus, useFormState, and use.

    • use(): The new experimental React 19 API, named use(), is engineered to read out the value of resources like Promises or Context out of the render function. It should bring one step closer to writing code for fetching asynchronous data or asynchronously managing state, more efficiently and without much boilerplate.

        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}>
                    <h2>{user.name}</h2>
                    <p>{user.email}</p>
                  </div>
                ))}
              </ul>
            );
          }; 
        export default UsersItems
      
      • useFormState: The useFormState hook acts as a manager for form input states. It provides a centralized way of observing their changes in values and updating them smartly. It allows updating the state based on the outcome of form actions. It takes two arguments: fn and initialState.

        It follows this syntax:

        const [state, formAction] = useFormState(fn, initialState, permalink?);
        const FormState = () => {
            const submitForm = (prevState, queryData) => {
                const name =  queryData.get("username");
                console.log(prevState); // previous form state
                if(name === 'john'){
                    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;
  • useFormStatus: The useFormStatus hook maintains the states of form fields and provides logical validation and submission state handling. It gives information concerning the last submission status of a form. It abstracts form management, making it relatively easy to have a centralized way of tracking and updating the form field status.

    It follows this syntax:

      const { pending, data, method, action } = useFormStatus();
    
  • useOptimistic: A useOptimistic hook allows updating the UI optimistically before server confirmation. It will secure a good user experience since users will not have to wait after acting. It comes in handy when you want to give immediate feedback to a user without waiting for a reply from the server.

    • Other Improvements in React 19

    • Ref as a prop: A major upgrade for refs is introduced in React 19: they may now be passed as props to functional components. In most circumstances, this removes the requirement for the forwardRef higher-order component (HOC).

    // Before React 19

    import React, { forwardRef } from 'react';
    
    const TestButton = forwardRef((props, ref) => (
    <button ref={ref}>
      {props.children}
    </button>
    ));
    

    // With React 19

    • const TestButton = ({ ref, children }) => (
      <button ref={ref}>
      {children}
      </button>
      );
      
    • <Context> as a Provider : In React 19, you can render <Context> as a provider instead of <Context.Provider>:

const ThemeContext = createContext('');

function App({children}) {
  return (
    <ThemeContext value="dark">
      {children}
    </ThemeContext>
  );  
}

React 19 RC Upgrade

To try out the React 19 RC(React Canary), follow the guide here. You can stay updated about the release date of React 19 by subscribing to the Canary Releases.

Conclusion

React19 has brought about a number of noteworthy upgrades and features that will assist developers in creating web apps that are both SEO-friendly and easy to develop, as can be seen by reviewing the list of features that are included with each releases of React. These features—which range from the Compiler to the recently added hooks—bring major upgrades that enable developers to improve their programming with faster results. Using React19 can improve the UI experience and performance for end users, help developers write easier-to-read and maintain code, and help businesses construct high-quality web applications.