Getting to Know React 19
(beta)
Jim Cummins
Network Access Team
https://slides.com/jimthedev/getting-to-know-react-19/fullscreen
What's coming in React 19?
Actions!
New hook: useActionState
React DOM: <form> actions, requestFormReset
New React DOM hook: useFormStatus
New hook: useOptimistic
https://slides.com/jimthedev/getting-to-know-react-19/fullscreen
useActionState
State
https://slides.com/jimthedev/getting-to-know-react-19/fullscreen
const [actionState, submitAction, isPending] = useActionState(
async (previousState, formData) => {
await updateName(String(formData.get("name")));
},
initialValue
);
const [value, setValue] = React.useState(initialValue);
<form action={submitAction}>
<input type="text" name="name" />
<button type="submit" disabled={isPending}>Update</button>
{isPending && <Pending />}
</form>
Action state
useFormStatus
https://slides.com/jimthedev/getting-to-know-react-19/fullscreen
import {useFormStatus} from 'react-dom';
function FutureWoodlandButton() {
const { pending, data, method, action } = useFormStatus();
return <button type="submit" disabled={pending} />
}
useOptimistic
https://slides.com/jimthedev/getting-to-know-react-19/fullscreen
function ChangeName({currentName, onUpdateName}) {
const [optimisticName, setOptimisticName] = useOptimistic(currentName);
const submitAction = async formData => {
const newName = formData.get("name");
setOptimisticName(newName);
const updatedName = await updateName(newName);
onUpdateName(updatedName);
};
return (
<form action={submitAction}>
<p>Your name is: {optimisticName}</p>
<p>
<label>Change Name:</label>
<input
type="text"
name="name"
disabled={currentName !== optimisticName}
/>
</p>
</form>
);
}
What (else) is changing?
-
useDeferredValue will have an initial value
-
Wording change: isLoading is becoming isPending
-
Context as a provider instead of Context.Provider
-
ref as a prop, no longer need forwardRef!
-
Cleanup functions for refs
-
New (limited use) API: use
https://slides.com/jimthedev/getting-to-know-react-19/fullscreen
Ref as a prop
https://slides.com/jimthedev/getting-to-know-react-19/fullscreen
const MyInput = React.forwardRef((props, ref) => (
<input placeholder={placeholder} ref={ref} />
));
<MyInput ref={ref} />
function MyInput({placeholder, ref}) {
return <input placeholder={placeholder} ref={ref} />
}
<MyInput ref={ref} />
Forward Ref
Ref as a prop
Cleanup functions for refs
https://slides.com/jimthedev/getting-to-know-react-19/fullscreen
<input
ref={(ref) => {
// ref created
// NEW: return a cleanup function to reset
// the ref when element is removed from DOM.
return () => {
// ref cleanup
};
}}
/>
Called when component unmounts
use()
https://slides.com/jimthedev/getting-to-know-react-19/fullscreen
import {use} from 'react';
function Comments({commentsPromise}) {
// `use` will suspend until the promise resolves.
const comments = use(commentsPromise);
return comments.map(comment => <p key={comment.id}>{comment}</p>);
}
function Page({commentsPromise}) {
// When `use` suspends in Comments,
// this Suspense boundary will be shown.
return (
<Suspense fallback={<div>Loading...</div>}>
<Comments commentsPromise={commentsPromise} />
</Suspense>
)
}
Probably don't use() this, though
But wait there's more!
- Support for Custom Elements
- Better Error Reporting
- Support for document metadata (title, link, and meta)
- Stylesheet precedence
- Support for async scripts
- Support for preloading resources
https://slides.com/jimthedev/getting-to-know-react-19/fullscreen
...and more
- Server Components
- Server actions "use server"
- Improved hydration (server side)
https://slides.com/jimthedev/getting-to-know-react-19/fullscreen
Deprecations
- Removed propTypes and defaultProps
- Removed string refs
- Removed legacy context using contextTypes / getChildContext
- Removed ReactDOM.render, use createRoot instead
https://slides.com/jimthedev/getting-to-know-react-19/fullscreen
More deprecations
Remove
https://slides.com/jimthedev/getting-to-know-react-19/fullscreen
import {act} from 'react/dom/test-utils'
import {act} from 'react'
react-test-renderer
@testing-library/react
Use
Remove
Use
What isn't in React 19?
- react-compiler (previously called react-forget)
- useEffectEvent
- Built-in Suspense Cache
https://slides.com/jimthedev/getting-to-know-react-19/fullscreen
Should I use React 19 today?
- Probably not in production, yet
- Will take some time for ecosystem to update
- types
- eslint plugins
- libraries
- etc.
- Try it out in playgrounds first, then wait
- Consider contributing and maintaining a react19 branch to woodland-seed (our app starter repo)
- Try out the codemods!
https://slides.com/jimthedev/getting-to-know-react-19/fullscreen
How to get involved?
- Frontend Architecture Working Group
- UI Guild
- woodland
- woodland-seed
- Talk to us about joining Woodland Contributors slack group
https://slides.com/jimthedev/getting-to-know-react-19/fullscreen
What to read?
- React 19
- React 19 Beta Blog Post
- React 19 Upgrade Guide
- React 19 Docs
- Other React things
- I Tried React Compiler by Nadia Makarevich
- Optimizing INP for a React App & Performance Learnings by TK Kinoshita
https://slides.com/jimthedev/getting-to-know-react-19/fullscreen
Thank you!
https://slides.com/jimthedev/getting-to-know-react-19/fullscreen
Getting to know React 19
By jimthedev
Getting to know React 19
- 123