In React, one of the main difficulties is ensuring that data changes such as submitting forms or updating users, are handled smoothly. Till now, developing these features meant developers needed to manually take care of attributes such as unfinished states, errors, optimistic updates and requests one after the other. As a consequence, the code was verbose, complex to follow and error-prone, mainly when writing for applications with multiple forms or many data streams.
With Actions in version 19, React lets you handle async actions in React components in a clearer and more convenient way. The Actions library lets developers take advantage of async functions in transitions to control the changes in state from the first request to the response.
You can use actions in React to alter data and React will handle problems like connecting the mutations with a convenience API.
- Pending State Management: Any time a request is made using an action, the pending state (isPending) automatically comes on and turns off when the request ends and the result is committed. There is no need for you to keep track of pending states using private variables anymore.
- Optimistic Updates: With the new useOptimistic hook, Actions let you quickly alert users by showing them a fictional UI state (optimistic update) before the response to their request comes. As a result, the UI looks and feels more responsive from the user’s perspective.
- Error Handling: Actions also work with Error Boundaries, allowing for displaying friendly error messages and correcting unwanted updates whenever a request fails. Because of this, users will always experience a consistent design.
- Automatic Form Handling: React 19 extends Actions to <form> elements, allowing you to pass functions directly to the action and formAction props. This makes it possible to handle form submissions without the need for external state management libraries or complex form handling logic.
1) New API: use
In React 19, we’re introducing a powerful new API designed to make data fetching in React components more efficient and straightforward: the use API. This API allows you to directly read and use resources (such as promises or context values) within the render phase of a component. It is a groundbreaking change, offering a more declarative and intuitive approach to handling asynchronous data, making React components more robust and responsive.
The use API is designed to let you read resources, such as promises or context values, directly in the render function of a React component. It eliminates the need for complex useEffect and useState setups for data fetching, making code cleaner and easier to maintain.
The use API works seamlessly with React’s Suspense, allowing you to show fallback content while data is being fetched. This integration makes it easy to create a smooth, user-friendly experience without complex state management.
How This Works:
- When UserProfile tries to read user data using use, React automatically suspends it.
- The Suspense component displays a fallback UI (“Loading user data…”) until the data is ready.
- Once the data is fetched, the UserProfile component is displayed with the user information.

import React, { Suspense, useState } from "react"
import ProductData from "./Component/ProductData"
const Application: React.FC<React.PropsWithChildren<any>> = () => {
const handleResponse = () => {
return new Promise((resolve, reject)=> {
fetch('https://dummyjson.com/products')
.then((e)=>e.json())
.then((e)=>{
if(e?.products) {
resolve(e.products)
} else {
reject('DATA NOT FOUND')
}
})
.catch((err)=>{
reject(err)
})
})
}
const [response] = useState(handleResponse())
return (
<div className="wrapper">
<h1>React 19</h1>
<Suspense fallback={<h1>Loading....</h1>}>
<ProductData response={response} />
</Suspense>
</div>
)
}
export default Application

import React, { use } from "react"
interface ValidateProductData {
response?: any
}
interface DataResponse {
title?: string
}
const ProductData: React.FC<React.PropsWithChildren<ValidateProductData>> = ({
response
}) => {
const data: DataResponse[] = use(response)
console.log(data)
return (
<ul>
{data && data.map((e: DataResponse) => <li>{e?.title}</li>)}
</ul>
)
}
export default ProductData
2) useFormStatus Hooks
In React, it is often needed to manage the form submission status with complex form-based user interfaces. To simplify monitoring when a form is submitted in React 19, experts introduced the useFormStatus hook.
With useFormStatus, you have access to the <form> status directly in any of the child components. It helps ensure that form components can be used more than once and react to the form’s current status.
- It eliminates the need for prop drilling in complex form components.
- It permits child elements to monitor the submission state which means they are more flexible for future projects.

import React, { useState } from "react"
import UserRegistration from "./Component/UserRegistration"
const Application: React.FC<React.PropsWithChildren<any>> = () => {
const [data, setData] = useState({})
const onSubmitting = async () => {
await fetch('https://dummyjson.com/products/add', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
...data
})
})
.then(res => res.json())
.then(console.log);
}
return (
<div className="wrapper">
<h1>React 19</h1>
<form action={onSubmitting}>
<UserRegistration setData={setData} />
</form>
</div>
)
}
export default Application

import React, { useEffect } from "react"
import { useFormStatus } from "react-dom"
const UserRegistration: React.FC<React.PropsWithChildren<any>> = ({
setData
}) => {
const { data, pending } = useFormStatus()
useEffect(() => {
if (data) {
setData(data)
}
}, [data])
return (
<>
<input name="email" type="text" placeholder="Enter Email Address" />
<input name="password" type="password" placeholder="Enter Password" />
<input name="cpassword" type="password" placeholder="Enter Confirm Password" />
<button disabled={pending}>Submit</button>
</>
)
}
export default UserRegistration
3) useActionState Hooks
Though Actions are effective for handling async functions, React 19 includes the useActionState hook to make the process less complex. The hook makes it possible to control the state of an Action (if it is pending, in error or a success) directly in the Action, with no extra state variables needed.
useActionState is a React hook that accepts an Action function and returns a wrapped version of that Action. Using this wrapper, React handles the action automatically and gives you the same API to work with asynchronous states.
How useActionState Works
- It takes an Action function as an argument.
- It returns the following values:
- The latest result of the Action.
- The pending state of the Action (isPending).
- Any error encountered during the Action.
- The latest result of the Action.


import React, { Fragment, useActionState } from "react"
interface ValidateErrors {
name?: string;
email?: string;
password?: string;
}
const ActionStateHook: React.FC<React.PropsWithChildren<any>> = () => {
const handlerFunction = async (previousState: unknown, formData: FormData) => {
const email = formData.get('email') as string
const name = formData.get('name') as string
const password = formData.get('password') as string
const errors: ValidateErrors = {}
if (!email) {
errors.email = 'Please enter the email address'
}
if (!name) {
errors.name = 'Please enter the name'
}
if (!password) {
errors.password = 'Please enter the password'
}
if (errors && Object.keys(errors).length) {
return {
errors: errors,
feildData: {
name,
email,
password
}
}
}
}
const [data, action, isPending] = useActionState(handlerFunction, undefined)
return (
<Fragment>
<form action={action}>
<input name="name" type="text" placeholder="Enter Full name" defaultValue={data?.feildData?.name} />
<span className="error">{data?.errors?.name}</span>
<input name="email" type="text" placeholder="Enter Email Address" defaultValue={data?.feildData?.email} />
<span className="error">{data?.errors?.email}</span>
<input name="password" type="text" placeholder="Enter Passowrd" defaultValue={data?.feildData?.password} />
<span className="error">{data?.errors?.password}</span>
<button>Submit</button>
</form>
</Fragment>
)
}
export default ActionStateHook
4) useOptimistic Hooks
With optimistic UI, the UI is changed before the task even begins so that the expected outcome appears in real time. As a result, people can use the website more quickly and easily.
With useOptimistic in React 19, you can perform optimistic UI updates very easily. Applying this hook causes the UI to show the new value at once, displaying it before the operation is finished.
The WebAPI responds to the user immediately, while the work is done by the async code.


"use client"
import { useActionState, useState, useOptimistic, useEffect } from "react"
import UseOptimisticHookForm from "./UseForm"
interface ValidateList {
title: string
}
const UseOptimisticHook = () => {
const [categories, setCategories] = useState<ValidateList[] | null>(null)
const [optimistic, setOptimistic] = useOptimistic<ValidateList[] | null>(categories)
const getCategories = async () => {
await fetch('https://www.aciledu.com/example/index.php?type=category')
.then((e) => e.json())
.then((response) => {
if (response?.data) {
setTimeout(()=>{
setCategories(response.data)
},1000)
}
})
}
useEffect(()=>{
getCategories()
},[])
const saveCategories = async (previousState: unknown, formData: FormData) => {
const subject = formData.get('subject') as string
const error: any = {}
if (!subject) {
error.message = 'Pleae enter the subject'
}
const optimisticCategory = { title: subject }
setOptimistic((prev)=>[...prev, optimisticCategory])
await fetch(`https://www.aciledu.com/example/index.php?type=saveCategory&title=${subject}`)
getCategories()
}
const [data, action] = useActionState(saveCategories, undefined)
return (
<>
<h1>List</h1>
<form action={action}>
<input name="subject" type="text" placeholder="Enter Subject" />
<button>Submit</button>
</form>
<UseOptimisticHookForm categories={optimistic} />
</>
)
}
export default UseOptimisticHook

const UseOptimisticHookForm = ({
categories
}:any) => {
return (
<ul>
{categories?.map((e:any)=><li>{e.title}</li>)}
</ul>
)
}
export default UseOptimisticHookForm