React 19: The Big Picture
๐ฑ This post is in the growth phase. It may still be useful as it grows up.
An App Dev's Guide to React 19:
What You Need to Know.
And Everything You Can Ignore.
chan.dev/react19
I'm @chantastic.
- I used to host React Podcast
- I work at WorkOS, where we build the best login box on the planet.
Trends in React 19
- Encourages TypeScript ๐ง
- Endorses Testing-Library ๐
- Embraces compilers ๐ค
- Engages the platform ๐
React 19 feature quadrants
quadrantChart
x-axis Internal --> External
y-axis Removed APIs --> New APIs
quadrant-1 Depends
quadrant-2 At release
quadrant-3 Today
quadrant-4 Tomorrow
React Compiler: [0.5, 0.9]
RSC and Server Actions: [0.75, 0.75]
Actions: [0.25, 0.8]
"Metadata, scripts, and stylesheets": [0.25, 0.7]
PropTypes and defaultProps: [0.5, 0.35]
PropTypes and defaultProps: [0.5, 0.35]
Legacy Render: [0.5, 0.25]
Legacy Context: [0.25, 0.3]
Testing Utilities: [0.25, 0.2]
SECRET_INTERNALS: [0.75, 0.2]
API Removals
React 18.3 warns for all removed APIs.
react-codemod
is available for project-wide migrations.
You canโt get fired with React 19
โ SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED
โ
_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE
You own what you (npm) install
โ 12k files with SECRET_INTERNALS references in GitHub
Type Safety and React 19
Runtime prop-checking removed
import PropTypes from 'prop-types';
Heading.propTypes = { text: PropTypes.string, }; Heading.defaultProps = { text: 'Hello, world!', };
interface Props { text?: string; }
export function Heading({ text = 'Hello, world!' }: Props) { return <h1>{text}</h1>;}
Better useReducer typings
useReducer<React.Reducer<State, Action>>((state, action) => state)useReducer((state: State, action: Action) => state)
useRef
requires an argument
useRef(); useRef(undefined);// consiquently, MutableRef is now deprecated
ref
cleanup required
<div ref={current => (instance = current)} /><div ref={current => {instance = current}} />
ReactElement
changed from any
to unknown
type Example = ReactElement["props"];// ^? Now 'unknown' (not 'any')// (Has no effect where type arguments are passed)
The JSX namespace in TypeScript
declare module "react" { namespace JSX { interface IntrinsicElements { "my-element": { myElementProps: string; }; } }}
See the React 19 RC Upgrade Guide for details and codemods.
Testing and React 19
Hey, just use Testing-Library, already.
Oh. Andact
is inreact
now.