What is New in React 19
React 19 introduces powerful tools for handling data updates, resource loading, and server-side rendering. It makes building interactive apps easier with new hooks like useActionState and useOptimistic, plus better support for forms, context, and metadata. These changes focus on smoother developer experience and faster performance across client and server environments.
Actions and Form Handling
useActionState Hook
This new hook manages async actions in forms. It tracks the latest result, provides a submit function, and shows if the action is pending. It handles errors and resets automatically.
const [error, submitAction, isPending] = useActionState(
async (state, formData) => {
const newName = formData.get('name');
const result = await updateName(newName);
if (result.error) return result.error;
return null;
},
null
);
Form Actions
Forms can now use functions directly as the action prop. React handles submission, pending states, and resets on success.
<form action={submitAction}>
<input name="name" />
<button type="submit" disabled={isPending}>Update</button>
</form>
useFormStatus Hook
Read the status of a form from any child component without passing props down. It shows if the form is pending.
import { useFormStatus } from 'react-dom';
function Button() {
const { pending } = useFormStatus();
return <button disabled={pending}>Submit</button>;
}
Optimistic Updates and Resources
useOptimistic Hook
Update the UI right away for better user feel, then sync with the server. It reverts changes if something goes wrong.
const [optimisticValue, addOptimistic] = useOptimistic(
messages,
(state, newMessage) => [...state, newMessage]
);
const action = useActionState(
async (_, formData) => {
const message = formData.get('message');
addOptimistic({ text: message });
const result = await submitMessage(message);
return result;
},
null
);
use Hook
Load promises or context values during render. The component pauses until the data is ready.
function Comments({ commentsPromise }) {
const comments = use(commentsPromise);
return comments.map(c => <p key={c.id}>{c.text}</p>);
}
Server Components and Static Rendering
Server Components
Now stable, these run only on the server to fetch data without sending extra code to the browser.
Server Actions
Mark functions with "use server" to run them on the server from client code. They work seamlessly with forms.
"use server";
export async function createPost(formData) {
// Server-side logic
}
Static APIs
New tools in react-dom/static for generating static HTML that waits for data before finishing.
import { prerender } from 'react-dom/static';
const { prelude, chunks } = await prerender(
<App />,
{ bootstrapScripts: ['/client.js'] }
);
Developer Experience Improvements
Ref as Prop
Pass refs directly to function components like regular props. No more need for forwardRef in many cases.
function MyComponent({ ref, ...props }) {
return <div {...props} ref={ref} />;
}
<MyComponent ref={myRef} />;
Context as Provider
Use the context object directly as a provider element for simpler code.
const ThemeContext = createContext();
<ThemeContext value={theme}>
<App />
</ThemeContext>;
Better Hydration Errors
Error messages now show clear diffs between server and client output to help fix mismatches quickly.
Ref Cleanup
Ref callbacks can return functions that run on unmount for cleaning up resources.
<input
ref={(node) => {
if (node) setup(node);
return () => cleanup(node);
}}
/>
Document and Resource Handling
Metadata Support
Add title, meta, and link tags right in your components. React moves them to the head automatically.
function Page({ title }) {
return (
<>
<title>{title}</title>
<meta name="description" content="..." />
<h1>{title}</h1>
</>
);
}
Stylesheet and Async Script Support
Render link and script tags in components. React handles loading order, deduplication, and Suspense integration.
<link
rel="stylesheet"
href="styles.css"
precedence="default"
/>
<script async src="analytics.js" />
Preloading APIs
New functions to preload DNS, connect to origins, or init resources early for better speed.
import { preload, preconnect } from 'react-dom';
preload('/image.jpg', { as: 'image' });
preconnect('https://api.example.com');
Other Enhancements
- useDeferredValue now takes an initial value for smoother starts.
- Third-party scripts in head or body are skipped during hydration to avoid errors.
- Ref callbacks must explicitly return undefined if no cleanup is needed.
- Improved support for custom elements and better error handling in transitions.
Deprecations and Breaking Changes
React 19 removes some old patterns and changes defaults for cleaner code:
| Feature | Change |
|---|---|
| forwardRef | Less necessary now; will be deprecated later |
| Context.Provider | Use Context directly; Provider will be deprecated |
| Legacy String Refs | Removed completely |
| ReactDOM.flushSync | Renamed to unstable_flushSync; will be removed |
| Third-Party Script Hydration | Now skipped to prevent mismatches |
| Ref Callback Returns | Must return cleanup function or undefined explicitly |
Upgrade Tips
- Run the React 19 codemod to update Context providers and other patterns.
- Test forms and actions in your app for new behaviors.
- Check hydration errors for better debugging during SSR.
- Update to the latest React DOM for static rendering if using SSG.
- Review ref usage in function components.
Final Thoughts
React 19 streamlines how you handle forms, data, and server logic, making apps more responsive and easier to maintain. With actions, optimistic updates, and better resource management, it bridges client and server development seamlessly. Start experimenting with these features to build more dynamic user interfaces today.