
Introduction to React 19: New Hooks and API Changes
Beyond the marquee features, React 19 includes a variety of new Hooks and tweaks to existing APIs that developers should know about:
New Hooks Recap: As discussed, the new Hooks introduced are:
-
useActionState
– manage form state/result tied to an Action function (What’s new in React 19 - Vercel). -
useFormStatus
– get submission status of a form (pending or not) (What’s new in React 19 - Vercel). -
useOptimistic
– handle optimistic UI updates with state and updater function (What’s new in React 19 - Vercel). -
use
(not a Hook, but a rendering utility) – suspend on promises in component code (What’s new in React 19 - Vercel).
These are all part of the core
react
(orreact-dom
foruseFormStatus
) package in v19. They primarily assist with forms and transitions, as covered above. The community is especially excited aboutuseOptimistic
for simplifying patterns that previously required libraries or extensive manual coding.-
ref
as a Prop: A long-standing quirk in React was that function components could not directly accept aref
(you had to wrap them inforwardRef
). React 19 finally changes this. Function components can now receive aref
just like any other prop (React v19 – React) (React v19 – React). For example:function MyInput({ placeholder, ref }) { return <input placeholder={placeholder} ref={ref} />; } // usage: const myRef = React.createRef(); <MyInput ref={myRef} placeholder="Type here" />;
This will work in React 19 –
ref
will be passed in and forwarded to the<input>
inside (React v19 – React). The big benefit is eliminating the boilerplate of creating a separate component just to forward a ref. The React team has said new codemods will automatically update your components to use this newref
prop, andReact.forwardRef
will eventually be deprecated (React v19 – React). Note: This only applies to function components; class components still handle refs as before (with the instance) (React v19 – React).Cleaner
useEffect
Cleanup for Refs: Another related ref improvement – React 19 allows ref callback functions to return a cleanup. Previously, if you used the callback ref pattern (ref={elem => { ... }}
), React would call your callback withnull
on unmount to signal cleanup. Now, you can instead return a function in the ref callback, and React will call that automatically on unmount (React v19 – React) (React v19 – React). For example:<input ref={el => { if (el) { // on mount: do something with el } return () => { // on unmount: cleanup, e.g., cancel subscription linked to el }; }} />
This pattern mirrors how
useEffect
cleanup works, making it more intuitive. It also avoids some tricky cases where the ref might be set to null while you still had logic to run. In fact, with this change, React will no longer call ref callbacks withnull
on unmount if you returned a cleanup function (React v19 – React). (If you don’t return a cleanup, the old behavior of anull
call remains for now.) TypeScript’s React types have been updated so that returning anything other than a function from a ref callback is considered an error, to catch mistakes where someone might accidentally return a value instead of undefined (React v19 – React). This is a subtle change, but it makes the ref system more robust and aligned with hooks conventions.Context as JSX: In a small ergonomic improvement, you no longer have to write
<MyContext.Provider value={...}>
– you can just render<MyContext value={...}>
in JSX (React v19 – React) (React v19 – React). In React 19, a Context object itself is now a valid component that defaults to rendering its Provider. This was mainly sugar to reduce keystrokes, but it also hints at React’s direction of simplifying APIs. A codemod will help convert the older usage, and eventually the explicit<Context.Provider>
might be deprecated (React v19 – React). For now, both work. Example:<ThemeContext value="dark"> <App /> </ThemeContext>
This makes Context usage a bit cleaner to read and write.
Form Methods and Events: The introduction of Actions also subtly changes how you might work with forms:
- If you were used to manually calling
event.preventDefault()
in form submits, note that usingaction={...}
on a form will handle that for you. You also don’t get the event object in your action function – you get theFormData
directly. This means code inside an Action doesn’t need to callnew FormData(formElement)
; React passes it in (What’s new in React 19 - Vercel) (What’s new in React 19 - Vercel). - Forms with
action
will by default reset their fields on successful submission. This is analogous to a traditional HTML form submission that navigates or reloads – after which the form is cleared. In React 19’s client-side forms, after your action runs, the form inputs are cleared unless you specifically hold their state. This caught some users by surprise, but it is intentional. It forces you to derive the form state from the server response (which is a good pattern for correctness). There is a workaround if needed (e.g., if you want to keep form values on success, you’d need to control them with state). - Because form actions can throw errors (reject promises) which are caught by Error Boundaries, you might want to have an Error Boundary around your form or higher in the tree to display submission errors. Alternatively, using
useActionState
provides the error in thestate
it returns, so you can handle it gracefully in the UI.
- If you were used to manually calling
Miscellaneous: A few other API notes:
- The
act()
testing utility has been moved fromreact-dom/test-utils
to the mainreact
package (you now importact
from'react'
) (React 19 Upgrade Guide – React) (React 19 Upgrade Guide – React). This means test code may need slight changes. The old import still exists in React 18.3 to warn you, but in React 19 it’s removed. - There’s a new
ReactDOM.flushSync
behavior where some changes in how it interacts with batching in 19, but unless you use it heavily, it shouldn’t affect common use. - React 19 supports Custom Elements (web components) much better: it will pass through props as properties where appropriate instead of always attributes (React v19 – React) (React v19 – React). This is great if you use web components with React – you no longer need hacks to get React to treat them properly. React now passes the Custom Elements Everywhere test suite 100% (React v19 – React).
-
<React.StrictMode>
in dev is still recommended and now slightly smarter (as discussed, less noisy re-rendering). If you had avoided StrictMode due to certain warnings, you might consider re-enabling it to prepare for future concurrent features.
- The
Date: