React 19 Beta Features and Updates

    Tuesday, April 30, 202410 min read519 views
    React 19 Beta Features and Updates

    In the last week of April, React unveiled its latest version React 19. The beta version is now available in the npm. This beta release aims to prepare libraries for React 19. Application developers should switch to 18.3.0 and pay close attention to React 19 getting stable as the libraries are work in progress based on feedback.

    without wasting time, let's explore the features and what's new in React 19.

    Newest Features in React 19

    In this section, developers can learn about what the major changes are and how you can adopt them effortlessly.

    Actions

    A common instance in React is performing data mutation and then renewing the state in response. Previously, if a user needed to submit a form to change their name, they needed to make an API request and then manage the response.

    In React 19, developers get added support for incorporating async functions in transition to deal with pending states, forms, error reporting, and updates automatically.

    Developers can make use of useTransition to handle the pending states like below:

    // Using pending state from Actions
    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 transitions will instantly make the isPending state true, create an async request, and change isPending to false after each transition. This will assist you in keeping the UI interactive and engaging while the data is continuously changing.

    The latest version React 19 also presents useOptimistic to administer optimistic updates and a new hook React.useActionState to manage cases for Actions. In react-dom, users need to add <form> Actions to manage forms automatically and useFormStatus to support the common cases for Actions in forms.

    // Using <form> Actions and useActionState
    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>
      );
    }

    New hook: useActionState

    A new hook is added 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
    });

    React DOM: <form> Actions

    With React 19's new <form> features for react-dom, actions are also integrated. When a <form> Action is a success, React will automatically reset the form for uncontrolled components. If users require to reset the <form> manually, they can call the new requestFormReset React DOM API.

    You want your next React development project to have a strong foundation?
    Hire React Developer from Angular Minds to get code organization and maintainability for complex applications

    React DOM: New hook: useFormStatus

    It is common knowledge in design systems to write design components that require access to insight or information about the <form> they are placed in, without prop drilling to the new components natively. There is a new hook useFormStatus:

    import {useFormStatus} from 'react-dom';
    
    function DesignButton() {
      const {pending} = useFormStatus();
      return <button type="submit" disabled={pending} />
    }

    New hook: useOptimistic

    When employing data mutation, a common UI pattern is to present the final state optimistically while the async request is underway. A new hook called useOptimistic is here to make things easier.

    function ChangeName({currentName, onUpdateName}) {
      const [optimisticName, setOptimisticName] = useOptimistic(currentName);
    
      const submitAction = async formData => {
        const newName = formData.get("name");
        setOptimisticName(newName);
        const updatedName = await updateName(newName);
        onUpdateName(updatedName);
      };
    
      return (
        <form action={submitAction}>
          <p>Your name is: {optimisticName}</p>
          <p>
            <label>Change Name:</label>
            <input
              type="text"
              name="name"
              disabled={currentName !== optimisticName}
            />
          </p>
        </form>
      );
    } 

    New API: use

    In React 19, a new API is introduced to read resources in render. For instance, developers can now read promise with use. React will suspend until the promise resolves.

    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>
      )
    }

    React Server Components

    Server Components

    The server components are one of the new features in React 19. They permit rendering components in advance, before bundling, and in an environment different from your client app or SSR server. This different environment is the 'server' in React Server Components.

    React 19 has all the React Server Component features that are in the Canary channel. Therefore, libraries that ship with server components can aim at React 19 as a peer dependency with a React server export condition.

    Server Actions

    To call async functions that are executed on the server, server actions allow client components. The framework will automatically create a reference to the server function, and transfer that reference to the client component when a Server action is defined with 'use server.' When that same function is called on the client, React will put a request to the server to complete the function, and send the result.

    Improvements in React 19

    ref as a prop

    Developers can now employ ref as a prop for function components in React 19:

    function MyInput({placeholder, ref}) {
      return <input placeholder={placeholder} ref={ref} />
    }
    
    //...
    <MyInput ref={ref} />

    Therefore, the new function components won't require forwardref. In future versions, forwarded will be deprecated and removed.

    Diffs for Hydration Errors

    Error reporting for hydration errors is also improved drastically in react-dom. For instance, instead of logging into multiple errors in DEV without much information about the mismatch we can log a single message with diff of mismatch:

    Uncaught Error: Hydration failed because the server rendered HTML didn’t match the client. As a result this tree will be regenerated on the client. This can happen if an SSR-ed Client Component used:
    
    - A server/client branch if (typeof window !== 'undefined').
    - Variable input such as Date.now() or Math.random() which changes each time it’s called.
    - Date formatting in a user’s locale which doesn’t match the server.
    - External changing data without sending a snapshot of it along with the HTML.
    - Invalid HTML tag nesting.
    
    It can also happen if the client has a browser extension installed which messes with the HTML before React loaded.
    
    https://react.dev/link/hydration-mismatch 
    
      <App>
        <span>
    +    Client
    -    Server
    
      at throwOnHydrationMismatch
      …

    <Context> as a provider

    Developers can render <Context> as a provider instead of <Context.Provider> in React 19:

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

    Cleanup functions for refs

    React 19 supports returning cleanup functions from ref callbacks:

    <input
      ref={(ref) => {
        // ref created
    
        // NEW: return a cleanup function to reset
        // the ref when element is removed from DOM.
        return () => {
          // ref cleanup
        };
      }}
    />

    useDeferredValue initial value

    An initialValue option to useDeferredValue option is also added:

    function Search({deferredValue}) {
      // On initial render the value is ''.
      // Then a re-render is scheduled with the deferredValue.
      const value = useDeferredValue(deferredValue, '');
      
      return (
        <Results query={value} />
      );
    }

    Support for Document Metadata

    In React, the components determine what metadata is suitable for the application and may be distant from where you render the <head> or React does not render the <head> at all.

    In React 19, there is added support for rendering document metadata tags in components natively:

    function BlogPost({post}) {
      return (
        <article>
          <h1>{post.title}</h1>
          <title>{post.title}</title>
          <meta name="author" content="Josh" />
          <link rel="author" href="https://twitter.com/joshcstory/" />
          <meta name="keywords" content={post.keywords} />
          <p>
            Eee equals em-see-squared...
          </p>
        </article>
      );
    }

    Support for Stylesheets

    The complexity of building a stylesheet capability that allows composability within the component is being solved in React 19. You will get in-depth integration of Concurrent Rendering on the Client and Streaming Rendering on the Server with built-in support for stylesheets.

    function ComponentOne() {
      return (
        <Suspense fallback="loading...">
          <link rel="stylesheet" href="foo" precedence="default" />
          <link rel="stylesheet" href="bar" precedence="high" />
          <article class="foo-class bar-class">
            {...}
          </article>
        </Suspense>
      )
    }
    
    function ComponentTwo() {
      return (
        <div>
          <p>{...}</p>
          <link rel="stylesheet" href="baz" precedence="default" />  <-- will be inserted between foo & bar
        </div>
      )
    }

    Support for Async Scripts

    In React 19, a well-supported async script is included by allowing you to render them anywhere in your component tree, inside the components that rely on the script, without having to administer relocating and deduplicating script situations.

    function MyComponent() {
      return (
        <div>
          <script async={true} src="..." />
          Hello World
        </div>
      )
    }
    
    function App() {
      <html>
        <body>
          <MyComponent>
          ...
          <MyComponent> // won't lead to duplicate script in the DOM
        </body>
      </html>
    }

    Support for Preloading Resources

    React 19 includes a new set of APIs for loading and preloading browser resources to make it easy and convenient to create a great developer experience and not something held back by insufficient resources.

    import { prefetchDNS, preconnect, preload, preinit } from 'react-dom'
    function MyComponent() {
      preinit('https://.../path/to/some/script.js', {as: 'script' }) // loads and executes this script eagerly
      preload('https://.../path/to/font.woff', { as: 'font' }) // preloads this font
      preload('https://.../path/to/stylesheet.css', { as: 'style' }) // preloads this stylesheet
      prefetchDNS('https://...') // when you may not actually request anything from this host
      preconnect('https://...') // when you will request something but aren't sure what
    }
    <!-- the above would result in the following DOM/HTML -->
    <html>
      <head>
        <!-- links/scripts are prioritized by their utility to early loading, not call order -->
        <link rel="prefetch-dns" href="https://...">
        <link rel="preconnect" href="https://...">
        <link rel="preload" as="font" href="https://.../path/to/font.woff">
        <link rel="preload" as="style" href="https://.../path/to/stylesheet.css">
        <script async="" src="https://.../path/to/some/script.js"></script>
      </head>
      <body>
        ...
      </body>
    </html>

    Compatibility with Third-Party Scripts and Extensions

    The hydration to account for third-party scripts and browser extensions is improved. The unexpected tags in the <head> and <body> will be passed over, avoiding the mismatch errors. If React requires to re-render the complete document due to an unrelated hydration mismatch, it will leave in place stylesheets placed by third-party scripts and browser extensions.

    Better Error Reporting

    The error handling is improved to remove duplication and to provide better alternatives to handle caught and uncaught errors. In React 19, you log a single error with all error information included:

    Error: hit
      at Throws
      at renderWithHooks
      …
    
    The above error occurred in the Throws component:
      at Throws
      at ErrorBoundary
      at App
    
    React will try to recreate this component tree from scratch using the error boundary you provided, ErrorBoundary.
      at ErrorBoundary
      at App

    Support for Custom Elements

    React 19 has complete support for custom elements and it succeeds all tests on Custom Elements Everywhere. Therefore, React 19 consist of properties that works on client and during the SSR. This is how it works:

    Server Side Rendering

    Props tranferred to a custom element will render as attributes if their type is a primitive value like string, number, or the value is true. Non-primitive types of props like object, symbol, function, or value false will be excluded.

    Client Side Rendering

    Props that are similar to a property on the Custom Element instance will be assigned as properties, or else they will be assigned as attributes.

    In a Nutshell

    With the React 19 release, there are significant improvements in various elements and components. Developers however will need to switch on the React 18.3.0 version until the progress in version 19 is final. Stay tuned to learn and explore the React 19 update guide.

    24
    Share
    Recruit the Best Remote React Developers
    Recruit the Best Remote React Developers
    Employ our pool of talented remote/offshore React developers to strengthen the efficiency and flexibility. Incorporate expertise for effective integration with your team and project requirements.
    Hire Now

    Related articles

    This website uses cookies to analyze website traffic and optimize your website experience. By continuing, you agree to our use of cookies as described in our Privacy Policy.