React v19 has been officially releasedReactv19hasbeenofficiallyreleasedReactv19hasbeenofficiallyreleased
9 Jan 2025
Share
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 actions
useOptimistic
use
ref as a prop
<Context> as a provider
useDeferredValue initial value
Support 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.
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.
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.
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.
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.
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.
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
constTodo=({ tasks, onAdded })=>{const[optTasks, setOptTasks]=useOptimistic<string[],string>( tasks,(currentState, newState)=>[...currentState, newState]);consthandleSubmit=async(formData:FormData)=>{const newTask = formData.get("task")?.toString()||"";setOptTasks(newTask);const response =awaitfetch(...);onAdded(response);};// optTasks gets updated before the API request is sent.return(...);};exportconstUseOptimistic=()=>{const[tasks, setTasks]=useState<string[]>([]);return(<Todo onAdded={(newTask)=>setTasks((oldState)=>[...oldState, newTask])} tasks={tasks}/>);};
typescript
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
const{ data }=useQuery({...});if(!show){returnnull;}return<p>API response:{data}</p>;
typescript
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.
Now, the useDeferredValue hook can have an initial value in its declaration.
Without useDeferredValue initial value
const[query, setQuery]=useState<string>('');const value =useDeferredValue(query);
typescript
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
const value =useDeferredValue(deferredValue,'');
typescript
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
constBlogPost=({ post })=>(<Helmet><title>{post.title}</title><meta name="author" content={post.author.name}/><meta name="keywords" content={post.keywords}/><link rel="author" href={`https://twitter.com/${post.author.handle}/`}/></Helmet>)
typescript
With document metadata
constBlogPost=({ post })=>(<title>{post.title}</title><meta name="author" content={post.author.name}/><meta name="keywords" content={post.keywords}/><link rel="author" href={`https://twitter.com/${post.author.handle}/`}/>)
typescript
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.
But wait - there's more.
Nearform publishes real-world learnings on data & AI, engineering, and digital strategy - with more merged in weekly.
Insights
Perspectives on AI in engineering, product development, and strategy, for enterprise executives.