React 19 landed in December 2024 as a stable release after the longest beta period in the library's history. It brings fundamental changes to how React works under the hood — changes that affect performance, server rendering, form handling, and even how you think about state. But if you're just starting to learn React, none of that should frighten you. Let's break down what's new, what matters, and what to actually learn first.

React 19 Is Here: The Key Changes

React 19 is the most significant major release since React 16 introduced Hooks in 2018. The headline changes are:

If you're on React 17 or 18: React 19 is backward-compatible for most codebases. The migration path is documented and most changes are additive, not breaking.

React Compiler: What It Means for Performance

This is the biggest architectural change. Today, React re-renders components when state changes — and as an optimisation, developers manually wrap expensive computations in useMemo() and functions in useCallback(). This is tedious, error-prone, and clutters code.

The React Compiler automatically analyses your components at build time and adds the necessary memoisation — no manual useMemo required. This means:

// Before React Compiler — you had to manually memoize
function ExpensiveList({ items, filter }) {
  const filtered = useMemo(
    () => items.filter(item => item.category === filter),
    [items, filter]
  );
  return <ul>{filtered.map(i => <li key={i.id}>{i.name}</li>)}</ul>;
}

// With React Compiler — just write the logic, compiler handles it
function ExpensiveList({ items, filter }) {
  const filtered = items.filter(item => item.category === filter);
  return <ul>{filtered.map(i => <li key={i.id}>{i.name}</li>)}</ul>;
}

Server Components and When to Use Them

React Server Components (RSC) run on the server and send HTML to the client — they never ship JavaScript to the browser. This sounds simple but has big implications: you can fetch data, read databases, and access the filesystem directly inside a component without any useEffect or API layer.

Use Server Components for:

Keep Client Components for:

// Server Component — runs only on server, can fetch data directly
async function BlogPost({ id }) {
  const post = await fetchPostFromDB(id); // direct DB access, no API needed
  return (
    <article>
      <h1>{post.title}</h1>
      <p>{post.content}</p>
      <LikeButton postId={id} /> {/* Client Component for interactivity */}
    </article>
  );
}

New Hooks: use(), useFormStatus(), and useFormState()

React 19 introduces several new hooks that solve common patterns with less boilerplate:

use()

The use() hook lets you read the value of a Promise or Context inside a component. Unlike useEffect, it can be called conditionally and works with Suspense for loading states.

import { use, Suspense } from 'react';

function UserProfile({ userPromise }) {
  const user = use(userPromise); // suspends until promise resolves
  return <div>{user.name}</div>;
}

// Wrap with Suspense for loading state
<Suspense fallback={<Spinner />}>
  <UserProfile userPromise={fetchUser(id)} />
</Suspense>

useFormStatus() and useFormState()

These hooks make form handling dramatically simpler. useFormStatus() tells a child component about its parent form's submission state — no prop drilling required. useFormState() manages form state in response to server actions.

import { useFormStatus } from 'react-dom';

function SubmitButton() {
  const { pending } = useFormStatus();
  return (
    <button disabled={pending}>
      {pending ? 'Submitting...' : 'Submit'}
    </button>
  );
}

Actions and Async Transitions

React 19 formalises the concept of "Actions" — async functions that handle state transitions, including pending states, errors, and optimistic updates. You can pass async functions directly to the action prop of a form.

async function createTodo(formData) {
  'use server'; // Server Action in Next.js
  const title = formData.get('title');
  await db.todos.create({ title });
}

export default function TodoForm() {
  return (
    <form action={createTodo}>
      <input name="title" />
      <SubmitButton />
    </form>
  );
}

What Beginners Should Still Learn First

All of the above is exciting, but if you're new to React, the fundamentals haven't changed. Learn these in order:

  1. JSX — what it is, how it compiles, expressions in curly braces
  2. Components — functions that return JSX, props, and composing components
  3. State with useState — local state, re-rendering, state updates
  4. Event handling — onClick, onChange, onSubmit
  5. Lists and keys — rendering arrays with .map(), why keys matter
  6. useEffect — side effects, cleanup, dependency array
  7. Lifting state up — sharing state between components
Common beginner mistake: Jumping straight to Redux, Next.js, or TypeScript before mastering the fundamentals above. Build three or four single-page React apps before adding any framework or library on top.

The Ecosystem in 2025: Next.js vs Remix vs TanStack Start

Once you know React basics, you'll need a framework for routing, server rendering, and deployment. Here's how the options compare:

For career purposes: Learn Next.js. It appears in the most job postings, has the largest community, and Vercel's deployment story is unmatched for getting projects live quickly.

Build Real Web Apps With React and Next.js

Our Web Development course covers React from the ground up through to deploying full-stack Next.js applications — with real projects at every step.

View the Web Development Course →
PC

Pal C

AI Engineer & Full-Stack Developer

Software engineer and AI specialist with 8+ years of experience. Has taught 500+ students from 15+ countries.