React 19: The long-expected features

saad elattar

Elattar Saad

Wed Apr 17 2024

4 min read15

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

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

FormWithStatus.jsx
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>
);
}

useFormState

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

FormWithState.jsx
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>
)
}

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.

FormWithOptimistic.jsx
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} />;
}

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:

Profile.jsx

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

The use hook will also be replacing the useContext hook:

Theme.jsx

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

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

ForwardRef

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

NoMoreForwardRef.jsx
// 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}/>
}

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/

Read next

Blossoming Intelligence: How to Run Spring AI Locally with Ollama

In this short article, we'll look at how easy it is to create a chat bot backend powered by Spring and Olama using the llama 3 model.

Sat May 11 2024

Read More

Getting started with native java apps with GraalVM

Native Image is a technology to ahead-of-time compile Java code to a standalone executable, called a native image. This executable includes the application classes, classes from its dependencies, runtime library classes, and statically linked native code from JDK.

Wed Apr 10 2024

Read More

Leveraging Spring Reactive, Functional Endpoints, Docker, and MongoDB

Blocking is a feature of classic servlet-based web frameworks like Spring MVC. Introduced in Spring 5, Spring WebFlux is a reactive framework that operates on servers like Netty and is completely non-blocking. Two programming paradigms are supported by Spring WebFlux. Annotations (Aspect Oriented Programming) and WebFlux.fn (Functional Programming).

Thu Feb 29 2024

Read More

NextJs meets Redux: A simple user PoC

Redux is a powerful state management library primarily used in JavaScript applications, particularly those built with frameworks like React. At its core, Redux provides a predictable state container for managing the state of an application in a more organised and centralised manner. It operates on a unidirectional data flow model, which helps in maintaining the consistency of application state and facilitates easier debugging and testing.

Thu Feb 15 2024

Read More
Saad Elattar © 2024
|