Getting Started with React 19
React 19 brings a wave of improvements that make building user interfaces cleaner and more intuitive. With enhanced server components, new hooks, and improved performance, it's worth getting up to speed with the latest features.
Server Components by Default
React 19 makes React Server Components (RSC) the default rendering mode. Components are now rendered on the server by default, reducing the JavaScript bundle sent to the client.
// This component runs on the server by default
async function UserProfile({ userId }) {
const user = await fetchUser(userId); // Direct DB call, no API layer needed
return (
<div>
<h1>{user.name}</h1>
<p>{user.bio}</p>
</div>
);
}
To create a client component that runs in the browser, you add a simple directive at the top of the file:
'use client';
import { useState } from 'react';
export function Counter() {
const [count, setCount] = useState(0);
return <button onClick={() => setCount(c => c + 1)}>{count}</button>;
}
The use() Hook
React 19 introduces a new use() hook that simplifies consuming values outside of render. It works with promises, context, and any thenable value.
import { use } from 'react';
function ThemeDisplay({ themePromise }) {
const theme = use(themePromise);
return <div style={{ background: theme }}>Welcome</div>;
}
// Or with context
function ThemeContextDisplay() {
const theme = use(ThemeContext);
return <div>Current theme: {theme}</div>;
}
Actions and useFormStatus
Form handling gets a major upgrade with native support for actions and form state.
'use client';
import { useFormStatus, useFormState } from 'react-dom';
function SubmitButton() {
const { pending, data } = useFormStatus();
return (
<button disabled={pending} type="submit">
{pending ? 'Submitting...' : 'Submit'}
</button>
);
}
export default function ContactForm() {
const [state, formAction] = useFormState(submitForm, null);
return (
<form action={formAction}>
<input name="email" type="email" required />
<SubmitButton />
{state?.error && <p>{state.error}</p>}
</form>
);
}
Compiler Optimizations
React 19 includes an experimental compiler that automatically optimizes your components. It eliminates unnecessary re-renders by tracking dependencies at compile time, removing the need for useMemo and useCallback in most cases.
// Before: manually memoized
const memoizedValue = useMemo(() => computeExpensive(a, b), [a, b]);
const handleClick = useCallback(() => doSomething(a), [a]);
// After: compiler handles it automatically
const value = computeExpensive(a, b); // No useMemo needed
function handleClick() { doSomething(a); } // No useCallback needed
Conclusion
React 19 represents a significant step forward in developer experience and performance. Server components reduce bundle sizes, the use() hook simplifies working with async values, and the compiler removes boilerplate. Start by migrating a non-critical component to see these benefits in action. The transition is incremental, so you can adopt features at your own pace while keeping your existing code working.