DEV Community

Cover image for React 19: The long-expected features
Elattar Saad
Elattar Saad

Posted on

React 19: The long-expected features

React 19 introduces a number of new features that will undoubtedly make the life of react developers simpler. While the release is not yet stable, you can test out the new features using the canary version.

npm i react@canary react-dom@canary
Enter fullscreen mode Exit fullscreen mode

React Forget

The react compiler (called "React Forget") in version 19 is nothing short of game-changing. Whiles some solutions included their own compilers to maximize developer efficiency, React initially solely operated in the browser.

Once a compiler is in place, React developers can concentrate on creating business features rather than worrying about things like momoization.
Yes, you heard that righ the momoization hooks (useMemo and useCallback) and memo API will no longer be needed since
the compiler will be handling that automatically and more efficiently without compromising the application performance nor the code base quality.

The React compiler is already been deployed in Instagram web app Production. You can see it in action in this ReactAdvanced Conf talk by Joe Savona and Mofei Zhang.

Actions

React 19 introduces the ability to run actions on either the server or the client using the directives "use client"
or "use server". Previously, Server Actions were used to transport data from the client to the server.
As a result, we now refer to them as "actions".

If you're acquainted with NextJs, the directives will come as no surprise.

To manage async actions, React provides a useFormStatus and useFormState hooks to handle the pending status and state to prevent multiple submissions of a form for instance.

Hooks

React 19 came with a set of new hooks that will either replace existing hooks or support the new of its features.

useFormStatus

import { useFormStatus } from "react-dom";
import action from './actions';

function Submit() {
  const {pending} = useFormStatus(); // will return {pending, data, method, action}
  return <button disabled={pending}>Submit</button>
}

export default function App() {
  return (
    <form action={action}>
      <Submit />
    </form>
  );
}
Enter fullscreen mode Exit fullscreen mode

useFormState

The actions can also return values, in that case we need use the useFormState hook.

import { useFormState } from "react-dom";

async function increment(previousState, formData) {
  return previousState + 1;
}

function StatefulForm({}) {
  const [state, formAction] = useFormState(increment, 0);
  return (
    <form>
      {state}
      <button formAction={formAction}>Increment</button>
    </form>
  )
}
Enter fullscreen mode Exit fullscreen mode

Know more about the useFormStatus and useFormState hooks.

useOptimistic

The useOptimistic hook can be used to provide the user with a temporary ui based on what they already submitted,
for instance showing the newly sent message while the data is processed on the server.

import { useOptimistic, useState, useRef } from "react";
import { deliverMessage } from "./actions.js";

function Thread({ messages, sendMessage }) {
  const formRef = useRef();
  async function formAction(formData) {
    addOptimisticMessage(formData.get("message")); // we get the input of the user; used to build the temp ui.
    formRef.current.reset(); // reset the form.
    await sendMessage(formData); // sending the data to the server asynchronosly.
  }
  const [optimisticMessages, addOptimisticMessage] = useOptimistic(
    messages,
    (state, newMessage) => [
      ...state,
      {
        text: newMessage,
        sending: true
      }
    ]
  );

  return (
    <>
      {optimisticMessages.map((message, index) => ( // getting the newly sent messages, mapping them into dom elements (optimistic UI).
        <div key={index}>
          {message.text}
          {!!message.sending && <small> (Sending...)</small>}
        </div>
      ))}
      <form action={formAction} ref={formRef}> {/* Just a simple form with action and ref*/}
        <input type="text" name="message" placeholder="Hello!" />
        <button type="submit">Send</button>
      </form>
    </>
  );
}

// Putting the Thread component in action by providing a state.
export default function App() {
  const [messages, setMessages] = useState([
    { text: "Hello there!", sending: false, key: 1 }
  ]);
  async function sendMessage(formData) {
    const sentMessage = await deliverMessage(formData.get("message"));
    setMessages((messages) => [...messages, { text: sentMessage }]);
  }
  return <Thread messages={messages} sendMessage={sendMessage} />;
}
Enter fullscreen mode Exit fullscreen mode

Know more about the useOptimistic hook.

useCallback and useMemo

As previously stated the momoization will be handled by the React Compiler, therefor the useMemo,
useCallback hooks and memo API won't make it to the version 19 of React.

use

The use hook is here to clean more the react code base, it will replace two widly used hooks (thank God): useEffect and useContext.

One of the famous use cases for the useEffect hook is data fetching, for this example we fetch the user details and return a UserProfile:


  // Using useEffect hook to fetch data.
  export const UserProfile = () => {
    const [userDetails, setUserDetails] = useState(null);

    useEffect(()=>{
      getUserDetails() // async function
        .then(data => {
          setUserDetails(data);
        })
        .catch(error => console.log(error))
    },[])

    if (!userDetails) return <p>Loading...</p>

    return (
      <p>{userDetails.name}</p>
    )

  }

  // Using use hook to fetch data.
  export const UserDetails = () => {  // another component for simplicity
    const userDetails = use(getUserDetails());
    return (
       <p>{userDetails.name}</p>
    )
  }

  export const UserProfile = () => {
    return (
      <Suspense fallback={<p>Loading...</p>}>
      <p>{userDetails.name}</p>
      </Suspense>
    )
  }
Enter fullscreen mode Exit fullscreen mode

The use hook will also be replacing the useContext hook:


// Using useContext hook to consume the theme context.
const theme = useContext(ThemeContext);

// Using use hook to consume the theme context
const theme = use(ThemeContext);

Enter fullscreen mode Exit fullscreen mode

ForwardRef

No more forwardRef! We can simply pass the ref down like any other prop without the use of forwardRef.

// Before
export const ProfilePicture = forwardRef(
  (props, ref) => ( // src and alt are props
    <img ref={ref} {...props}/>
  )
)

// On v19
export const ProfilePicture = (ref, ...props) => {
  <img ref={ref} {...props}/>
}
Enter fullscreen mode Exit fullscreen mode

SEO

React will enable the usage of the <title>, <meta>, and <link> tags anywhere in the App, improving SEO performance.
Previously, libraries like as react-helmet were used for this.

Summary

In my perspective, React v19 will deliver a lot of relevant and required enhancements, allowing developers to focus more on important features that matter!

Resources

https://react.dev/blog/2024/02/15/react-labs-what-we-have-been-working-on-february-2024#react-compiler
https://react.dev/blog/2023/03/22/react-labs-what-we-have-been-working-on-march-2023#react-optimizing-compiler
https://www.youtube.com/watch?v=qOQClO3g8-Y
https://react.dev/reference/react/

Top comments (0)