React v19 has been officially released
We highlight the differences between the old and new ways of coding in React
The latest version of React, v19, has been officially released. It includes a range of new features designed to simplify app development. In this post, we’ll walk through these new features and explore the differences compared to previous implementations without React 19.
We have a working demo, if you’d like to try it yourself.
Table of contents
useTransition
useActionState
useFormStatus
form
actionsuseOptimistic
use
ref
as a prop<Context>
as a provideruseDeferredValue
initial valueSupport for document metadata
useTransition
We no longer need to manage loading states manually for handling async functions, thanks to the new useTransition
hook. This hook takes care of managing the async call and its state, as demonstrated below.
Without useTransition
In this case, we still need to manage internal loading states, and the UI may become unresponsive at times due to multiple state updates. As you can see, we need to manually update the isTransitioning
variable according to the state of the API request. Therefore, we need to set it to true
before sending the request and to false
after receiving a response.
With useTransition
Calling startTransition
manages the transition state of the async function and updates it based on the function’s execution. The transition state will automatically be set to true
and revert to false
once all Promises
are settled. We don’t need to maintain isTransitioning
because useTransition
handles it automatically.
In addition, the useTransition
hook ensures that the UI remains responsive and interactive, even while internal state updates are occurring in the background.
useActionState and useFormStatus
In the past, we had to create and manage internal states to handle form actions, as we saw earlier. To address this, React 19 has introduced two new powerful hooks that take care of managing internal form states for us.
Without useActionState and useFormStatus
As you can see, both are traditional React components used to implement a minimalist to-do list app. We can highlight a few key points:
Three internal states (
tasks
,isHandling
andtask
) are required to manage the tasks list, the API request status and the input field value.The internal states need to be updated at different times based on the UI requirements.
The API request status must be passed as a prop to the button to enable or disable it appropriately.
With useActionState and useFormStatus
With the new hook, we no longer need to manage those three internal states, as the action will have an initial state and return everything we need to implement the UI. Additionally, we can use the new useFormStatus
hook to capture the form status throughout the React tree without the need for prop drilling or using React context as you can see in the FormButton
component. The hook itself will automatically capture the closest form status.
form actions
The new form
actions help us manage internal form field states, meaning we no longer need to manage and map all form field values in an internal state. The action provides the FormData
, from which we can retrieve the value of each field using the field’s name
.
Without actions
The traditional way to handle forms is by mapping all fields to an internal state (either a single object or multiple primitives) and creating a submit callback function to handle the form submission. This means we need to retrieve all field values from internal states or refs before initiating the API request.
With actions
Using form
actions, we can retrieve the form state through the FormData
parameter, eliminating the need to map internal states to each individual form field. The useFormStatus
hook also works perfectly with form
actions. Now we no longer need to map form fields to internal states or refs because we can retrieve their values using the field names from the FormData
object.
useOptimistic
The new useOptimistic
hook allows us to apply updates optimistically while an async request is still in progress. We don’t need to wait for the API response to update the UI if we’re confident the request will succeed based on the client state, because we assume it succeeds. Otherwise, the UI changes will need to be reverted.
Without useOptimistic
We need to wait for the API request to finish in order to update the UI. Therefore, we can’t delay updating the UI until after firing the API request and synchronising it later when we receive a response. The UI is updated synchronously.
With useOptimistic
Now the Todo
component can update its internal state optimistically without waiting for the API response. Once the response is received, the parent component can synchronise the internal state with the updated API state. All of this happens behind the scenes, so the user remains unaware of the optimistic state being synchronised with the API.
use
The new use
hook allows us to call hooks conditionally to resolve a Promise
or read a value from any Context
, for example. The hook itself can only be called inside a component, just like the old hooks.
use
also supports Suspense
by default.
Without use
We can’t use hooks conditionally; all hooks must be called unconditionally, before any conditional rendering. This means the API request will be triggered even if it’s not needed.
With use
By using the new use
hook, we can conditionally render before calling the API. This means we will only trigger the necessary API requests.
ref as a prop
In React 19, we can consume references as a regular prop instead of using the forwardRef
higher-order function.
Without ref as a prop
Using forwardRef
, we can forward the ref
to the correct internal element.
With ref as a prop
We can retrieve the ref using regular props, as usual. forwardRef
will be deprecated in future releases.
<Context> as a provider
In React v19, we can render a <Context>
as a provider instead of using the explicit <Context.Provider>
property.
Without context as a provider
With context as a provider
useDeferredValue initial value
Now, the useDeferredValue
hook can have an initial value in its declaration.
Without useDeferredValue initial value
As you can see, we need to create an internal state (query
) with an initial value and pass it to the useDeferredValue
hook.
With useDeferredValue initial value
We no longer need to create the internal state because we can provide an initial value as the second parameter to the useDeferredValue
hook.
Support for document metadata
Now we can provide metadata tags like <title>
, <link>
and <meta>
within the React component tree to replace the high-level ones. As a result, we no longer need to use third-party libraries like react-helmet
or write manual functions to manage them.
Without document metadata
With document metadata
Conclusion
Using the new React v19 features can make basic tasks easier to achieve without writing as much code as in previous versions.
Apart from the new hooks, React v19 also introduced new features. You can check the official blog post here.
Insight, imagination and expertly engineered solutions to accelerate and sustain progress.
Contact